* Re: Linux 6.6.151
2026-08-09 18:34 Linux 6.6.151 Greg Kroah-Hartman
@ 2026-08-09 18:34 ` Greg Kroah-Hartman
0 siblings, 0 replies; 2+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-09 18:34 UTC (permalink / raw)
To: linux-kernel, akpm, torvalds, stable; +Cc: lwn, jslaby, Greg Kroah-Hartman
diff --git a/Makefile b/Makefile
index c05bee52eb20..05c17f548757 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
PATCHLEVEL = 6
-SUBLEVEL = 150
+SUBLEVEL = 151
EXTRAVERSION =
NAME = Pinguïn Aangedreven
diff --git a/arch/powerpc/boot/simpleboot.c b/arch/powerpc/boot/simpleboot.c
index c80691d83880..27591df41e9e 100644
--- a/arch/powerpc/boot/simpleboot.c
+++ b/arch/powerpc/boot/simpleboot.c
@@ -68,7 +68,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
/* finally, setup the timebase */
node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type",
"cpu", sizeof("cpu"));
- if (!node)
+ if (node < 0)
fatal("Cannot find cpu node\n");
timebase = fdt_getprop(_dtb_start, node, "timebase-frequency", &size);
if (timebase && (size == 4))
diff --git a/arch/powerpc/boot/treeboot-akebono.c b/arch/powerpc/boot/treeboot-akebono.c
index e3cc2599869c..1b529037480f 100644
--- a/arch/powerpc/boot/treeboot-akebono.c
+++ b/arch/powerpc/boot/treeboot-akebono.c
@@ -146,7 +146,7 @@ void platform_init(char *userdata)
node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type",
"cpu", sizeof("cpu"));
- if (!node)
+ if (node < 0)
fatal("Cannot find cpu node\n");
timebase = fdt_getprop(_dtb_start, node, "timebase-frequency", &size);
if (timebase && (size == 4))
diff --git a/arch/powerpc/boot/treeboot-currituck.c b/arch/powerpc/boot/treeboot-currituck.c
index d53e8a592f81..5b5363b74f9f 100644
--- a/arch/powerpc/boot/treeboot-currituck.c
+++ b/arch/powerpc/boot/treeboot-currituck.c
@@ -102,7 +102,7 @@ void platform_init(void)
node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type",
"cpu", sizeof("cpu"));
- if (!node)
+ if (node < 0)
fatal("Cannot find cpu node\n");
timebase = fdt_getprop(_dtb_start, node, "timebase-frequency", &size);
if (timebase && (size == 4))
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c
index 1326de55fda6..e04952bb4360 100644
--- a/arch/powerpc/platforms/ps3/mm.c
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -615,6 +615,7 @@ static int dma_ioc0_map_pages(struct ps3_dma_region *r, unsigned long phys_addr,
fail_map:
for (iopage--; 0 <= iopage; iopage--) {
+ offset = (1 << r->page_size) * iopage;
lv1_put_iopte(0,
c->bus_addr + offset,
c->lpar_addr + offset,
diff --git a/arch/s390/kvm/pci.c b/arch/s390/kvm/pci.c
index 6e6726b2a441..17fedfc7bb99 100644
--- a/arch/s390/kvm/pci.c
+++ b/arch/s390/kvm/pci.c
@@ -225,7 +225,7 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib,
bool assist)
{
struct page *pages[1], *aibv_page, *aisb_page = NULL;
- unsigned int msi_vecs, idx;
+ unsigned int msi_vecs, idx, size;
struct zpci_gaite *gaite;
unsigned long hva, bit;
struct kvm *kvm;
@@ -239,6 +239,10 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib,
if (zdev->gisa == 0)
return -EINVAL;
+ /* AIF already enabled for the device */
+ if (zdev->kzdev->fib.fmt0.aibv != 0)
+ return -EINVAL;
+
kvm = zdev->kzdev->kvm;
msi_vecs = min_t(unsigned int, fib->fmt0.noi, zdev->max_msi);
@@ -248,6 +252,14 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib,
return gisc;
/* Replace AIBV address */
+ size = BITS_TO_LONGS(msi_vecs + fib->fmt0.aibvo) * sizeof(unsigned long);
+ npages = DIV_ROUND_UP((fib->fmt0.aibv & ~PAGE_MASK) + size, PAGE_SIZE);
+ /* AIBV cannot span more than 1 page */
+ if (npages > 1) {
+ rc = -EINVAL;
+ goto out;
+ }
+
idx = srcu_read_lock(&kvm->srcu);
hva = gfn_to_hva(kvm, gpa_to_gfn((gpa_t)fib->fmt0.aibv));
npages = pin_user_pages_fast(hva, 1, FOLL_WRITE | FOLL_LONGTERM, pages);
@@ -263,6 +275,12 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib,
/* Pin the guest AISB if one was specified */
if (fib->fmt0.sum == 1) {
+ /* AISB must be dword aligned */
+ if (fib->fmt0.aisb & 0x7) {
+ rc = -EINVAL;
+ goto unpin1;
+ }
+
idx = srcu_read_lock(&kvm->srcu);
hva = gfn_to_hva(kvm, gpa_to_gfn((gpa_t)fib->fmt0.aisb));
npages = pin_user_pages_fast(hva, 1, FOLL_WRITE | FOLL_LONGTERM,
@@ -291,6 +309,11 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib,
AIRQ_IV_GUESTVEC,
phys_to_virt(fib->fmt0.aibv));
+ if (!zdev->aibv) {
+ rc = -ENOMEM;
+ goto free_aisb;
+ }
+
spin_lock_irq(&aift->gait_lock);
gaite = aift->gait + zdev->aisb;
@@ -327,6 +350,9 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib,
rc = kvm_zpci_set_airq(zdev);
return rc;
+free_aisb:
+ airq_iv_free_bit(aift->sbv, zdev->aisb);
+ zdev->aisb = 0;
unlock:
mutex_unlock(&aift->aift_lock);
unpin2:
diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index 1a068859a418..001777f77b3a 100644
--- a/arch/um/drivers/vector_kern.c
+++ b/arch/um/drivers/vector_kern.c
@@ -1007,6 +1007,9 @@ static int vector_mmsg_rx(struct vector_private *vp, int budget)
*/
dev_kfree_skb_irq(skb);
vp->estats.rx_encaps_errors++;
+ (*skbuff_vector) = NULL;
+ mmsg_vector++;
+ skbuff_vector++;
continue;
}
if (header_check > 0) {
diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
index 63006c33ac43..c8af4e687f40 100644
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -167,14 +167,6 @@ static void avic_deactivate_vmcb(struct vcpu_svm *svm)
if (!sev_es_guest(svm->vcpu.kvm))
svm_set_intercept(svm, INTERCEPT_CR8_WRITE);
- /*
- * If running nested and the guest uses its own MSR bitmap, there
- * is no need to update L0's msr bitmap
- */
- if (is_guest_mode(&svm->vcpu) &&
- vmcb12_is_intercept(&svm->nested.ctl, INTERCEPT_MSR_PROT))
- return;
-
/* Enabling MSR intercept for x2APIC registers */
svm_set_x2apic_msr_interception(svm, true);
}
diff --git a/drivers/accel/qaic/qaic_control.c b/drivers/accel/qaic/qaic_control.c
index de8b17e2b29e..e59acc39c3fa 100644
--- a/drivers/accel/qaic/qaic_control.c
+++ b/drivers/accel/qaic/qaic_control.c
@@ -782,7 +782,7 @@ static int encode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
break;
}
trans_hdr = (struct qaic_manage_trans_hdr *)(user_msg->data + user_len);
- if (trans_hdr->len < sizeof(trans_hdr) ||
+ if (trans_hdr->len < sizeof(*trans_hdr) ||
size_add(user_len, trans_hdr->len) > user_msg->len) {
ret = -EINVAL;
break;
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index df8f8a1a3a34..5d5dff2440ee 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -330,7 +330,7 @@ struct ahci_port_priv {
struct ahci_host_priv {
/* Input fields */
unsigned int flags; /* AHCI_HFLAG_* */
- u32 mask_port_map; /* mask out particular bits */
+ u32 mask_port_map; /* Mask of valid ports */
void __iomem * mmio; /* bus-independent mem map */
u32 cap; /* cap to use */
@@ -381,6 +381,21 @@ struct ahci_host_priv {
int port);
};
+/*
+ * Return true if a port should be ignored because it is excluded from
+ * the host port map.
+ */
+static inline bool ahci_ignore_port(struct ahci_host_priv *hpriv,
+ unsigned int portid)
+{
+ if (portid >= hpriv->nports)
+ return true;
+ /* mask_port_map not set means that all ports are available */
+ if (!hpriv->mask_port_map)
+ return false;
+ return !(hpriv->mask_port_map & (1 << portid));
+}
+
extern int ahci_ignore_sss;
extern const struct attribute_group *ahci_shost_groups[];
diff --git a/drivers/ata/ahci_brcm.c b/drivers/ata/ahci_brcm.c
index 70c3a33eee6f..481aab4d9b96 100644
--- a/drivers/ata/ahci_brcm.c
+++ b/drivers/ata/ahci_brcm.c
@@ -288,6 +288,9 @@ static unsigned int brcm_ahci_read_id(struct ata_device *dev,
/* Re-initialize and calibrate the PHY */
for (i = 0; i < hpriv->nports; i++) {
+ if (ahci_ignore_port(hpriv, i))
+ continue;
+
rc = phy_init(hpriv->phys[i]);
if (rc)
goto disable_phys;
diff --git a/drivers/ata/ahci_ceva.c b/drivers/ata/ahci_ceva.c
index 11a2c199a7c2..b2918ad8e7e0 100644
--- a/drivers/ata/ahci_ceva.c
+++ b/drivers/ata/ahci_ceva.c
@@ -206,15 +206,21 @@ static int ceva_ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
goto disable_clks;
for (i = 0; i < hpriv->nports; i++) {
+ if (ahci_ignore_port(hpriv, i))
+ continue;
+
rc = phy_init(hpriv->phys[i]);
if (rc)
- goto disable_rsts;
+ goto exit_phys;
}
/* De-assert the controller reset */
ahci_platform_deassert_rsts(hpriv);
for (i = 0; i < hpriv->nports; i++) {
+ if (ahci_ignore_port(hpriv, i))
+ continue;
+
rc = phy_power_on(hpriv->phys[i]);
if (rc) {
phy_exit(hpriv->phys[i]);
@@ -224,14 +230,24 @@ static int ceva_ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
return 0;
-disable_rsts:
- ahci_platform_deassert_rsts(hpriv);
-
disable_phys:
while (--i >= 0) {
+ if (ahci_ignore_port(hpriv, i))
+ continue;
+
phy_power_off(hpriv->phys[i]);
phy_exit(hpriv->phys[i]);
}
+ ahci_platform_assert_rsts(hpriv);
+ goto disable_clks;
+
+exit_phys:
+ while (--i >= 0) {
+ if (ahci_ignore_port(hpriv, i))
+ continue;
+
+ phy_exit(hpriv->phys[i]);
+ }
disable_clks:
ahci_platform_disable_clks(hpriv);
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 86fa5dc7dd99..f10148354b34 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -541,6 +541,7 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
hpriv->saved_port_map = port_map;
}
+ /* mask_port_map not set means that all ports are available */
if (hpriv->mask_port_map) {
dev_warn(dev, "masking port_map 0x%lx -> 0x%lx\n",
port_map,
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index 581704e61f28..1153b9f7ff12 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -49,6 +49,9 @@ int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)
int rc, i;
for (i = 0; i < hpriv->nports; i++) {
+ if (ahci_ignore_port(hpriv, i))
+ continue;
+
rc = phy_init(hpriv->phys[i]);
if (rc)
goto disable_phys;
@@ -70,6 +73,9 @@ int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)
disable_phys:
while (--i >= 0) {
+ if (ahci_ignore_port(hpriv, i))
+ continue;
+
phy_power_off(hpriv->phys[i]);
phy_exit(hpriv->phys[i]);
}
@@ -88,6 +94,9 @@ void ahci_platform_disable_phys(struct ahci_host_priv *hpriv)
int i;
for (i = 0; i < hpriv->nports; i++) {
+ if (ahci_ignore_port(hpriv, i))
+ continue;
+
phy_power_off(hpriv->phys[i]);
phy_exit(hpriv->phys[i]);
}
@@ -435,6 +444,20 @@ static int ahci_platform_get_firmware(struct ahci_host_priv *hpriv,
return 0;
}
+static u32 ahci_platform_find_max_port_id(struct device *dev)
+{
+ u32 max_port = 0;
+
+ for_each_child_of_node_scoped(dev->of_node, child) {
+ u32 port;
+
+ if (!of_property_read_u32(child, "reg", &port))
+ max_port = max(max_port, port);
+ }
+
+ return max_port;
+}
+
/**
* ahci_platform_get_resources - Get platform resources
* @pdev: platform device to get resources for
@@ -462,6 +485,7 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
struct ahci_host_priv *hpriv;
struct device_node *child;
u32 mask_port_map = 0;
+ u32 max_port;
if (!devres_open_group(dev, NULL, GFP_KERNEL))
return ERR_PTR(-ENOMEM);
@@ -553,15 +577,17 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
goto err_out;
}
+ /* find maximum port id for allocating structures */
+ max_port = ahci_platform_find_max_port_id(dev);
/*
- * If no sub-node was found, we still need to set nports to
- * one in order to be able to use the
+ * Set nports according to maximum port id. Clamp at
+ * AHCI_MAX_PORTS, warning message for invalid port id
+ * is generated later.
+ * When DT has no sub-nodes max_port is 0, nports is 1,
+ * in order to be able to use the
* ahci_platform_[en|dis]able_[phys|regulators] functions.
*/
- if (child_nodes)
- hpriv->nports = child_nodes;
- else
- hpriv->nports = 1;
+ hpriv->nports = min(AHCI_MAX_PORTS, max_port + 1);
hpriv->phys = devm_kcalloc(dev, hpriv->nports, sizeof(*hpriv->phys), GFP_KERNEL);
if (!hpriv->phys) {
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index fc2c508c41bd..b3dfd882a7dd 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -106,6 +106,12 @@ static const unsigned int ata_eh_flush_timeouts[] = {
UINT_MAX,
};
+static const unsigned int ata_eh_standby_timeouts[] = {
+ 15000, /* Some drives may be slow to standby */
+ /* but don't hold up a suspend too long waiting for them */
+ UINT_MAX,
+};
+
static const unsigned int ata_eh_other_timeouts[] = {
5000, /* same rationale as identify timeout */
10000, /* ditto */
@@ -147,6 +153,8 @@ ata_eh_cmd_timeout_table[ATA_EH_CMD_TIMEOUT_TABLE_SIZE] = {
.timeouts = ata_eh_other_timeouts, },
{ .commands = CMDS(ATA_CMD_FLUSH, ATA_CMD_FLUSH_EXT),
.timeouts = ata_eh_flush_timeouts },
+ { .commands = CMDS(ATA_CMD_STANDBYNOW1),
+ .timeouts = ata_eh_standby_timeouts },
{ .commands = CMDS(ATA_CMD_VERIFY),
.timeouts = ata_eh_reset_timeouts },
};
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 80a45e11fb5b..8700bc2fdade 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -4026,7 +4026,7 @@ static int mv_platform_probe(struct platform_device *pdev)
/*
* Simple resource validation ..
*/
- if (unlikely(pdev->num_resources != 1)) {
+ if (unlikely(pdev->num_resources != 1 && pdev->num_resources != 2)) {
dev_err(&pdev->dev, "invalid number of resources\n");
return -EINVAL;
}
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 89c1d6ec7ada..2587349f60ce 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -2437,6 +2437,15 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd)
/* update device id */
ub->dev_info.dev_id = ub->ub_number;
+ /*
+ * ->state and ->ublksrv_pid are owned by the driver and only read back
+ * by userspace, but they come from the copied-in dev_info, so reset
+ * them. Otherwise a device added with ->state != DEAD looks live while
+ * ->ub_disk is still NULL.
+ */
+ ub->dev_info.state = UBLK_S_DEV_DEAD;
+ ub->dev_info.ublksrv_pid = -1;
+
/*
* 64bit flags will be copied back to userspace as feature
* negotiation result, so have to clear flags which driver
diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
index 25fcd00c6a17..4784da07dd8a 100644
--- a/drivers/bluetooth/btintel.c
+++ b/drivers/bluetooth/btintel.c
@@ -2922,6 +2922,9 @@ static int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb)
{
struct intel_tlv *tlv = (void *)&skb->data[5];
+ if (skb->len < 5 + sizeof(*tlv) + sizeof(tlv->val[0]))
+ goto recv_frame;
+
/* The first event is always an event type TLV */
if (tlv->type != INTEL_TLV_TYPE_ID)
goto recv_frame;
diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index ab68c2cbd79e..d424c6a9be3a 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -760,30 +760,24 @@ static int btmtk_usb_uhw_reg_write(struct hci_dev *hdev, u32 reg, u32 val)
static int btmtk_usb_uhw_reg_read(struct hci_dev *hdev, u32 reg, u32 *val)
{
struct btmtk_data *data = hci_get_priv(hdev);
- int pipe, err;
- void *buf;
-
- buf = kzalloc(4, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
+ u8 buf[sizeof(u32)];
+ int err;
- pipe = usb_rcvctrlpipe(data->udev, 0);
- err = usb_control_msg(data->udev, pipe, 0x01,
- 0xDE,
- reg >> 16, reg & 0xffff,
- buf, 4, USB_CTRL_GET_TIMEOUT);
- if (err < 0) {
+ *val = 0;
+ err = usb_control_msg_recv(data->udev, 0, 0x01,
+ 0xDE,
+ reg >> 16, reg & 0xffff,
+ buf, sizeof(buf), USB_CTRL_GET_TIMEOUT,
+ GFP_KERNEL);
+ if (err) {
bt_dev_err(hdev, "Failed to read uhw reg(%d)", err);
- goto err_free_buf;
+ return err;
}
*val = get_unaligned_le32(buf);
bt_dev_dbg(hdev, "reg=%x, value=0x%08x", reg, *val);
-err_free_buf:
- kfree(buf);
-
- return err;
+ return 0;
}
static int btmtk_usb_reg_read(struct hci_dev *hdev, u32 reg, u32 *val)
@@ -833,7 +827,7 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
if (dev_id == 0x7922) {
err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_SUBSYS_RST, &val);
- if (err < 0)
+ if (err)
return err;
val |= 0x00002020;
err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_SUBSYS_RST, val);
@@ -843,7 +837,7 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
if (err < 0)
return err;
err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_SUBSYS_RST, &val);
- if (err < 0)
+ if (err)
return err;
val |= BIT(0);
err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_SUBSYS_RST, val);
@@ -852,14 +846,14 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
msleep(100);
} else if (dev_id == 0x7925) {
err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_RESET_REG_CONNV3, &val);
- if (err < 0)
+ if (err)
return err;
val |= (1 << 5);
err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_RESET_REG_CONNV3, val);
if (err < 0)
return err;
err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_RESET_REG_CONNV3, &val);
- if (err < 0)
+ if (err)
return err;
val &= 0xFFFF00FF;
val |= (1 << 13);
@@ -870,7 +864,7 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
if (err < 0)
return err;
err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_RESET_REG_CONNV3, &val);
- if (err < 0)
+ if (err)
return err;
val |= (1 << 0);
err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_RESET_REG_CONNV3, val);
@@ -880,13 +874,13 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
if (err < 0)
return err;
err = btmtk_usb_uhw_reg_read(hdev, MTK_UDMA_INT_STA_BT, &val);
- if (err < 0)
+ if (err)
return err;
err = btmtk_usb_uhw_reg_write(hdev, MTK_UDMA_INT_STA_BT1, 0x000000FF);
if (err < 0)
return err;
err = btmtk_usb_uhw_reg_read(hdev, MTK_UDMA_INT_STA_BT1, &val);
- if (err < 0)
+ if (err)
return err;
msleep(100);
} else {
@@ -896,7 +890,7 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
if (err < 0)
return err;
err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_WDT_STATUS, &val);
- if (err < 0)
+ if (err)
return err;
/* Reset the bluetooth chip via USB interface. */
err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_SUBSYS_RST, 1);
@@ -906,13 +900,13 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
if (err < 0)
return err;
err = btmtk_usb_uhw_reg_read(hdev, MTK_UDMA_INT_STA_BT, &val);
- if (err < 0)
+ if (err)
return err;
err = btmtk_usb_uhw_reg_write(hdev, MTK_UDMA_INT_STA_BT1, 0x000000FF);
if (err < 0)
return err;
err = btmtk_usb_uhw_reg_read(hdev, MTK_UDMA_INT_STA_BT1, &val);
- if (err < 0)
+ if (err)
return err;
/* MT7921 need to delay 20ms between toggle reset bit */
msleep(20);
@@ -920,7 +914,7 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
if (err < 0)
return err;
err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_SUBSYS_RST, &val);
- if (err < 0)
+ if (err)
return err;
}
diff --git a/drivers/cpufreq/ia64-acpi-cpufreq.c b/drivers/cpufreq/ia64-acpi-cpufreq.c
index f692729068f5..c6bdc455517f 100644
--- a/drivers/cpufreq/ia64-acpi-cpufreq.c
+++ b/drivers/cpufreq/ia64-acpi-cpufreq.c
@@ -302,7 +302,7 @@ acpi_cpufreq_cpu_init (
}
-static void
+static int
acpi_cpufreq_cpu_exit (
struct cpufreq_policy *policy)
{
@@ -316,6 +316,8 @@ acpi_cpufreq_cpu_exit (
kfree(policy->freq_table);
kfree(data);
}
+
+ return (0);
}
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
index b10f7a1b77f1..508bd6f68f1e 100644
--- a/drivers/cpufreq/powernow-k8.c
+++ b/drivers/cpufreq/powernow-k8.c
@@ -1083,6 +1083,7 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol)
err_out_exit_acpi:
powernow_k8_cpu_exit_acpi(data);
+ kfree(data->powernow_table);
err_out:
kfree(data);
diff --git a/drivers/dma/idxd/cdev.c b/drivers/dma/idxd/cdev.c
index 5ded4a0887bc..e885d5af485b 100644
--- a/drivers/dma/idxd/cdev.c
+++ b/drivers/dma/idxd/cdev.c
@@ -293,6 +293,7 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp)
fdev->parent = cdev_dev(idxd_cdev);
fdev->bus = &dsa_bus_type;
fdev->type = &idxd_cdev_file_type;
+ idxd_wq_get(wq);
rc = dev_set_name(fdev, "file%d", ctx->id);
if (rc < 0) {
@@ -306,13 +307,14 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp)
goto failed_dev_add;
}
- idxd_wq_get(wq);
mutex_unlock(&wq->wq_lock);
return 0;
failed_dev_add:
failed_dev_name:
+ mutex_unlock(&wq->wq_lock);
put_device(fdev);
+ return rc;
failed_ida:
failed_set_pasid:
if (device_user_pasid_enabled(idxd))
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 6a384bd46952..f1d5af20363e 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -934,16 +934,13 @@ static int sun6i_dma_terminate_all(struct dma_chan *chan)
spin_lock_irqsave(&vchan->vc.lock, flags);
- if (vchan->cyclic) {
- vchan->cyclic = false;
- if (pchan && pchan->desc) {
- struct virt_dma_desc *vd = &pchan->desc->vd;
- struct virt_dma_chan *vc = &vchan->vc;
+ if (pchan && pchan->desc && pchan->desc != pchan->done) {
+ struct virt_dma_desc *vd = &pchan->desc->vd;
- list_add_tail(&vd->node, &vc->desc_completed);
- }
+ vchan_terminate_vdesc(vd);
}
+ vchan->cyclic = false;
vchan_get_all_descriptors(&vchan->vc, &head);
if (pchan) {
diff --git a/drivers/firmware/stratix10-svc.c b/drivers/firmware/stratix10-svc.c
index 2f263d1a6bd1..f723869c5b2d 100644
--- a/drivers/firmware/stratix10-svc.c
+++ b/drivers/firmware/stratix10-svc.c
@@ -1083,14 +1083,16 @@ void *stratix10_svc_allocate_memory(struct stratix10_svc_chan *chan,
struct gen_pool *genpool = chan->ctrl->genpool;
size_t s = roundup(size, 1 << genpool->min_alloc_order);
- pmem = devm_kzalloc(chan->ctrl->dev, sizeof(*pmem), GFP_KERNEL);
+ pmem = kzalloc(sizeof(*pmem), GFP_KERNEL);
if (!pmem)
return ERR_PTR(-ENOMEM);
guard(mutex)(&svc_mem_lock);
va = gen_pool_alloc(genpool, s);
- if (!va)
+ if (!va) {
+ kfree(pmem);
return ERR_PTR(-ENOMEM);
+ }
memset((void *)va, 0, s);
pa = gen_pool_virt_to_phys(genpool, va);
@@ -1116,6 +1118,7 @@ EXPORT_SYMBOL_GPL(stratix10_svc_allocate_memory);
void stratix10_svc_free_memory(struct stratix10_svc_chan *chan, void *kaddr)
{
struct stratix10_svc_data_mem *pmem;
+
guard(mutex)(&svc_mem_lock);
list_for_each_entry(pmem, &svc_data_mem, node)
@@ -1124,10 +1127,9 @@ void stratix10_svc_free_memory(struct stratix10_svc_chan *chan, void *kaddr)
(unsigned long)kaddr, pmem->size);
pmem->vaddr = NULL;
list_del(&pmem->node);
+ kfree(pmem);
return;
}
-
- list_del(&svc_data_mem);
}
EXPORT_SYMBOL_GPL(stratix10_svc_free_memory);
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index bf701766f4d0..bd07cb24f233 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -1258,9 +1258,20 @@ static int pca953x_restore_context(struct pca953x_chip *chip)
regcache_mark_dirty(chip->regmap);
ret = pca953x_regcache_sync(chip);
if (ret)
- return ret;
+ goto err;
+
+ ret = regcache_sync(chip->regmap);
+ if (ret)
+ goto err;
+
+ return 0;
- return regcache_sync(chip->regmap);
+err:
+ if (chip->client->irq > 0)
+ disable_irq(chip->client->irq);
+ regcache_cache_only(chip->regmap, true);
+
+ return ret;
}
static void pca953x_save_context(struct pca953x_chip *chip)
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c
index ee37ecb615cb..77e84e0e6c1b 100644
--- a/drivers/gpio/gpio-pch.c
+++ b/drivers/gpio/gpio-pch.c
@@ -97,7 +97,7 @@ struct pch_gpio {
struct pch_gpio_reg_data pch_gpio_reg;
int irq_base;
enum pch_type_t ioh;
- spinlock_t spinlock;
+ raw_spinlock_t spinlock;
};
static void pch_gpio_set(struct gpio_chip *gpio, unsigned int nr, int val)
@@ -106,7 +106,7 @@ static void pch_gpio_set(struct gpio_chip *gpio, unsigned int nr, int val)
struct pch_gpio *chip = gpiochip_get_data(gpio);
unsigned long flags;
- spin_lock_irqsave(&chip->spinlock, flags);
+ raw_spin_lock_irqsave(&chip->spinlock, flags);
reg_val = ioread32(&chip->reg->po);
if (val)
reg_val |= BIT(nr);
@@ -114,7 +114,7 @@ static void pch_gpio_set(struct gpio_chip *gpio, unsigned int nr, int val)
reg_val &= ~BIT(nr);
iowrite32(reg_val, &chip->reg->po);
- spin_unlock_irqrestore(&chip->spinlock, flags);
+ raw_spin_unlock_irqrestore(&chip->spinlock, flags);
}
static int pch_gpio_get(struct gpio_chip *gpio, unsigned int nr)
@@ -132,7 +132,7 @@ static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned int nr,
u32 reg_val;
unsigned long flags;
- spin_lock_irqsave(&chip->spinlock, flags);
+ raw_spin_lock_irqsave(&chip->spinlock, flags);
reg_val = ioread32(&chip->reg->po);
if (val)
@@ -146,7 +146,7 @@ static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned int nr,
pm |= BIT(nr);
iowrite32(pm, &chip->reg->pm);
- spin_unlock_irqrestore(&chip->spinlock, flags);
+ raw_spin_unlock_irqrestore(&chip->spinlock, flags);
return 0;
}
@@ -157,12 +157,12 @@ static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned int nr)
u32 pm;
unsigned long flags;
- spin_lock_irqsave(&chip->spinlock, flags);
+ raw_spin_lock_irqsave(&chip->spinlock, flags);
pm = ioread32(&chip->reg->pm);
pm &= BIT(gpio_pins[chip->ioh]) - 1;
pm &= ~BIT(nr);
iowrite32(pm, &chip->reg->pm);
- spin_unlock_irqrestore(&chip->spinlock, flags);
+ raw_spin_unlock_irqrestore(&chip->spinlock, flags);
return 0;
}
@@ -264,7 +264,7 @@ static int pch_irq_type(struct irq_data *d, unsigned int type)
return 0;
}
- spin_lock_irqsave(&chip->spinlock, flags);
+ raw_spin_lock_irqsave(&chip->spinlock, flags);
/* Set interrupt mode */
im = ioread32(im_reg) & ~(PCH_IM_MASK << (im_pos * 4));
@@ -276,7 +276,7 @@ static int pch_irq_type(struct irq_data *d, unsigned int type)
else if (type & IRQ_TYPE_EDGE_BOTH)
irq_set_handler_locked(d, handle_edge_irq);
- spin_unlock_irqrestore(&chip->spinlock, flags);
+ raw_spin_unlock_irqrestore(&chip->spinlock, flags);
return 0;
}
@@ -373,7 +373,7 @@ static int pch_gpio_probe(struct pci_dev *pdev,
chip->ioh = id->driver_data;
chip->reg = chip->base;
pci_set_drvdata(pdev, chip);
- spin_lock_init(&chip->spinlock);
+ raw_spin_lock_init(&chip->spinlock);
pch_gpio_setup(chip);
ret = devm_gpiochip_add_data(dev, &chip->gpio, chip);
@@ -406,9 +406,9 @@ static int __maybe_unused pch_gpio_suspend(struct device *dev)
struct pch_gpio *chip = dev_get_drvdata(dev);
unsigned long flags;
- spin_lock_irqsave(&chip->spinlock, flags);
+ raw_spin_lock_irqsave(&chip->spinlock, flags);
pch_gpio_save_reg_conf(chip);
- spin_unlock_irqrestore(&chip->spinlock, flags);
+ raw_spin_unlock_irqrestore(&chip->spinlock, flags);
return 0;
}
@@ -418,11 +418,11 @@ static int __maybe_unused pch_gpio_resume(struct device *dev)
struct pch_gpio *chip = dev_get_drvdata(dev);
unsigned long flags;
- spin_lock_irqsave(&chip->spinlock, flags);
+ raw_spin_lock_irqsave(&chip->spinlock, flags);
iowrite32(0x01, &chip->reg->reset);
iowrite32(0x00, &chip->reg->reset);
pch_gpio_restore_reg_conf(chip);
- spin_unlock_irqrestore(&chip->spinlock, flags);
+ raw_spin_unlock_irqrestore(&chip->spinlock, flags);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index ded2cc476880..8a2072056e3e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -2637,6 +2637,19 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
return 0;
}
+static void amdgpu_restore_umd_profile_pstate_after_runpm(struct amdgpu_device *adev)
+{
+ enum amd_dpm_forced_level level;
+ uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |
+ AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |
+ AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK |
+ AMD_DPM_FORCED_LEVEL_PROFILE_PEAK;
+
+ level = amdgpu_dpm_get_performance_level(adev);
+ if (level & profile_mode_mask)
+ amdgpu_asic_update_umd_stable_pstate(adev, true);
+}
+
static int amdgpu_pmops_runtime_resume(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
@@ -2680,6 +2693,8 @@ static int amdgpu_pmops_runtime_resume(struct device *dev)
if (amdgpu_device_supports_px(drm_dev))
drm_dev->switch_power_state = DRM_SWITCH_POWER_ON;
+
+ amdgpu_restore_umd_profile_pstate_after_runpm(adev);
adev->in_runpm = false;
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
index 44367f03316f..94de300d5dc5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
@@ -219,7 +219,20 @@ static bool amdgpu_gtt_mgr_intersects(struct ttm_resource_manager *man,
const struct ttm_place *place,
size_t size)
{
- return !place->lpfn || amdgpu_gtt_mgr_has_gart_addr(res);
+ const struct drm_mm_node *const node = &to_ttm_range_mgr_node(res)->mm_nodes[0];
+ const u32 num_pages = PFN_UP(size);
+
+ if (!place->lpfn)
+ return true;
+
+ if (!amdgpu_gtt_mgr_has_gart_addr(res))
+ return false;
+
+ if (place->fpfn >= (node->start + num_pages) ||
+ (place->lpfn && place->lpfn <= node->start))
+ return false;
+
+ return true;
}
/**
@@ -237,7 +250,20 @@ static bool amdgpu_gtt_mgr_compatible(struct ttm_resource_manager *man,
const struct ttm_place *place,
size_t size)
{
- return !place->lpfn || amdgpu_gtt_mgr_has_gart_addr(res);
+ const struct drm_mm_node *const node = &to_ttm_range_mgr_node(res)->mm_nodes[0];
+ const u32 num_pages = PFN_UP(size);
+
+ if (!place->lpfn)
+ return true;
+
+ if (!amdgpu_gtt_mgr_has_gart_addr(res))
+ return false;
+
+ if (node->start < place->fpfn ||
+ (place->lpfn && (node->start + num_pages) > place->lpfn))
+ return false;
+
+ return true;
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 052ff38c2049..1499638182bc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -1976,6 +1976,18 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
else
gtt_size = (uint64_t)amdgpu_gtt_size << 20;
+ /* Cap GTT so that it does not exceed total physical RAM. */
+ if (adev->flags & AMD_IS_APU) {
+ u64 phys_ram = (u64)totalram_pages() << PAGE_SHIFT;
+
+ if (gtt_size > phys_ram) {
+ gtt_size = phys_ram;
+ dev_info(adev->dev,
+ "Capping GTT to %uM to not exceed available system memory\n",
+ (unsigned int)(gtt_size / (1024 * 1024)));
+ }
+ }
+
/* Initialize GTT memory pool */
r = amdgpu_gtt_mgr_init(adev, gtt_size);
if (r) {
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index de6495c2b2f4..5ed8aff7bd81 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -2977,10 +2977,14 @@ static int kfd_ioctl_set_debug_trap(struct file *filep, struct kfd_process *p, v
goto out;
}
- /* Check if target is still PTRACED. */
+ /*
+ * Verify debugger has permission to debug target process.
+ * For cross-process debugging, require active ptrace relationship.
+ * This applies to ALL operations to prevent unauthorized interference.
+ */
rcu_read_lock();
- if (target != p && args->op != KFD_IOC_DBG_TRAP_DISABLE
- && ptrace_parent(target->lead_thread) != current) {
+ if (target != p && ptrace_parent(target->lead_thread) != current
+ && target->debugger_process != p) {
pr_err("PID %i is not PTRACED and cannot be debugged\n", args->pid);
r = -EPERM;
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
index 30af6b7dda8c..f01df3e57bd9 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
@@ -520,6 +520,9 @@ int kfd_criu_restore_event(struct file *devkfd,
ret = create_other_event(p, ev, &ev_priv->event_id);
break;
+ default:
+ ret = -EINVAL;
+ break;
}
mutex_unlock(&p->event_mutex);
@@ -541,15 +544,27 @@ int kfd_criu_checkpoint_events(struct kfd_process *p,
int ret = 0;
struct kfd_event *ev;
uint32_t ev_id;
+ uint32_t num_events;
- uint32_t num_events = kfd_get_num_events(p);
+ /* Serialize the count and the walk below against concurrent event
+ * create/destroy. Those paths take only p->event_mutex, not the
+ * p->mutex held by the CRIU checkpoint caller, so without this the
+ * event_idr can grow between kfd_get_num_events() and the loop and the
+ * walk writes past the ev_privs allocation.
+ */
+ mutex_lock(&p->event_mutex);
- if (!num_events)
+ num_events = kfd_get_num_events(p);
+ if (!num_events) {
+ mutex_unlock(&p->event_mutex);
return 0;
+ }
ev_privs = kvzalloc(num_events * sizeof(*ev_privs), GFP_KERNEL);
- if (!ev_privs)
+ if (!ev_privs) {
+ mutex_unlock(&p->event_mutex);
return -ENOMEM;
+ }
idr_for_each_entry(&p->event_idr, ev, ev_id) {
@@ -590,6 +605,8 @@ int kfd_criu_checkpoint_events(struct kfd_process *p,
i++;
}
+ mutex_unlock(&p->event_mutex);
+
ret = copy_to_user(user_priv_data + *priv_data_offset,
ev_privs, num_events * sizeof(*ev_privs));
if (ret) {
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
index d11a71e8aa14..3f6fc8d0984d 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
@@ -344,7 +344,7 @@ int pqm_create_queue(struct process_queue_manager *pqm,
false);
if (retval) {
dev_err(dev->adev->dev, "failed to allocate process context bo\n");
- return retval;
+ goto err_allocate_pqn;
}
memset(pdd->proc_ctx_cpu_ptr, 0, AMDGPU_MES_PROC_CTX_SIZE);
}
diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c
index d223176912b6..e409029638b0 100644
--- a/drivers/gpu/drm/armada/armada_fbdev.c
+++ b/drivers/gpu/drm/armada/armada_fbdev.c
@@ -43,10 +43,10 @@ static int armada_fbdev_create(struct drm_fb_helper *fbh,
struct drm_fb_helper_surface_size *sizes)
{
struct drm_device *dev = fbh->dev;
+ struct fb_info *info = fbh->info;
struct drm_mode_fb_cmd2 mode;
struct armada_framebuffer *dfb;
struct armada_gem_object *obj;
- struct fb_info *info;
int size, ret;
void *ptr;
@@ -87,12 +87,6 @@ static int armada_fbdev_create(struct drm_fb_helper *fbh,
if (IS_ERR(dfb))
return PTR_ERR(dfb);
- info = drm_fb_helper_alloc_info(fbh);
- if (IS_ERR(info)) {
- ret = PTR_ERR(info);
- goto err_fballoc;
- }
-
info->fbops = &armada_fb_ops;
info->fix.smem_start = obj->phys_addr;
info->fix.smem_len = obj->obj.size;
@@ -107,10 +101,6 @@ static int armada_fbdev_create(struct drm_fb_helper *fbh,
(unsigned long long)obj->phys_addr);
return 0;
-
- err_fballoc:
- dfb->fb.funcs->destroy(&dfb->fb);
- return ret;
}
static int armada_fb_probe(struct drm_fb_helper *fbh,
diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c
index 851f0baf9460..24ff1cab4e25 100644
--- a/drivers/gpu/drm/display/drm_dp_helper.c
+++ b/drivers/gpu/drm/display/drm_dp_helper.c
@@ -2930,6 +2930,18 @@ int drm_dp_get_pcon_max_frl_bw(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
int bw;
u8 buf;
+ if (!drm_dp_is_branch(dpcd))
+ return 0;
+
+ if (dpcd[DP_DPCD_REV] < 0x11)
+ return 0;
+
+ if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
+ return 0;
+
+ if ((port_cap[0] & DP_DS_PORT_TYPE_MASK) != DP_DS_PORT_TYPE_HDMI)
+ return 0;
+
buf = port_cap[2];
bw = buf & DP_PCON_MAX_FRL_BW;
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 9691c93f19a0..298a8974adad 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -499,20 +499,7 @@ int drm_fb_helper_init(struct drm_device *dev,
}
EXPORT_SYMBOL(drm_fb_helper_init);
-/**
- * drm_fb_helper_alloc_info - allocate fb_info and some of its members
- * @fb_helper: driver-allocated fbdev helper
- *
- * A helper to alloc fb_info and the member cmap. Called by the driver
- * within the fb_probe fb_helper callback function. Drivers do not
- * need to release the allocated fb_info structure themselves, this is
- * automatically done when calling drm_fb_helper_fini().
- *
- * RETURNS:
- * fb_info pointer if things went okay, pointer containing error code
- * otherwise
- */
-struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper)
+static struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper)
{
struct device *dev = fb_helper->dev->dev;
struct fb_info *info;
@@ -538,17 +525,8 @@ struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper)
framebuffer_release(info);
return ERR_PTR(ret);
}
-EXPORT_SYMBOL(drm_fb_helper_alloc_info);
-/**
- * drm_fb_helper_release_info - release fb_info and its members
- * @fb_helper: driver-allocated fbdev helper
- *
- * A helper to release fb_info and the member cmap. Drivers do not
- * need to release the allocated fb_info structure themselves, this is
- * automatically done when calling drm_fb_helper_fini().
- */
-void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper)
+static void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper)
{
struct fb_info *info = fb_helper->info;
@@ -561,7 +539,6 @@ void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper)
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
}
-EXPORT_SYMBOL(drm_fb_helper_release_info);
/**
* drm_fb_helper_unregister_info - unregister fb_info framebuffer device
@@ -1851,6 +1828,13 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper)
height = dev->mode_config.max_height;
drm_client_modeset_probe(&fb_helper->client, width, height);
+
+ info = drm_fb_helper_alloc_info(fb_helper);
+ if (IS_ERR(info)) {
+ mutex_unlock(&fb_helper->lock);
+ return PTR_ERR(info);
+ }
+
ret = drm_fb_helper_single_fb_probe(fb_helper);
if (ret < 0) {
if (ret == -EAGAIN) {
@@ -1859,13 +1843,12 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper)
}
mutex_unlock(&fb_helper->lock);
- return ret;
+ goto err_drm_fb_helper_release_info;
}
drm_setup_crtcs_fb(fb_helper);
fb_helper->deferred_setup = false;
- info = fb_helper->info;
info->var.pixclock = 0;
/* Need to drop locks to avoid recursive deadlock in
@@ -1888,6 +1871,10 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper)
mutex_unlock(&kernel_fb_helper_lock);
return 0;
+
+err_drm_fb_helper_release_info:
+ drm_fb_helper_release_info(fb_helper);
+ return ret;
}
/**
diff --git a/drivers/gpu/drm/drm_fbdev_dma.c b/drivers/gpu/drm/drm_fbdev_dma.c
index 13cd754af311..e1e3b30f77c1 100644
--- a/drivers/gpu/drm/drm_fbdev_dma.c
+++ b/drivers/gpu/drm/drm_fbdev_dma.c
@@ -78,10 +78,10 @@ static int drm_fbdev_dma_helper_fb_probe(struct drm_fb_helper *fb_helper,
{
struct drm_client_dev *client = &fb_helper->client;
struct drm_device *dev = fb_helper->dev;
+ struct fb_info *info = fb_helper->info;
struct drm_client_buffer *buffer;
struct drm_gem_dma_object *dma_obj;
struct drm_framebuffer *fb;
- struct fb_info *info;
u32 format;
struct iosys_map map;
int ret;
@@ -114,12 +114,6 @@ static int drm_fbdev_dma_helper_fb_probe(struct drm_fb_helper *fb_helper,
fb_helper->buffer = buffer;
fb_helper->fb = buffer->fb;
- info = drm_fb_helper_alloc_info(fb_helper);
- if (IS_ERR(info)) {
- ret = PTR_ERR(info);
- goto err_drm_client_buffer_vunmap;
- }
-
drm_fb_helper_fill_info(info, fb_helper, sizes);
info->fbops = &drm_fbdev_dma_fb_ops;
@@ -138,10 +132,6 @@ static int drm_fbdev_dma_helper_fb_probe(struct drm_fb_helper *fb_helper,
return 0;
-err_drm_client_buffer_vunmap:
- fb_helper->fb = NULL;
- fb_helper->buffer = NULL;
- drm_client_buffer_vunmap(buffer);
err_drm_client_buffer_delete:
drm_client_framebuffer_delete(buffer);
return ret;
diff --git a/drivers/gpu/drm/drm_fbdev_generic.c b/drivers/gpu/drm/drm_fbdev_generic.c
index b4659cd6285a..2f07490b4baf 100644
--- a/drivers/gpu/drm/drm_fbdev_generic.c
+++ b/drivers/gpu/drm/drm_fbdev_generic.c
@@ -73,8 +73,8 @@ static int drm_fbdev_generic_helper_fb_probe(struct drm_fb_helper *fb_helper,
{
struct drm_client_dev *client = &fb_helper->client;
struct drm_device *dev = fb_helper->dev;
+ struct fb_info *info = fb_helper->info;
struct drm_client_buffer *buffer;
- struct fb_info *info;
size_t screen_size;
void *screen_buffer;
u32 format;
@@ -100,12 +100,6 @@ static int drm_fbdev_generic_helper_fb_probe(struct drm_fb_helper *fb_helper,
goto err_drm_client_framebuffer_delete;
}
- info = drm_fb_helper_alloc_info(fb_helper);
- if (IS_ERR(info)) {
- ret = PTR_ERR(info);
- goto err_vfree;
- }
-
drm_fb_helper_fill_info(info, fb_helper, sizes);
info->fbops = &drm_fbdev_generic_fb_ops;
@@ -122,12 +116,10 @@ static int drm_fbdev_generic_helper_fb_probe(struct drm_fb_helper *fb_helper,
info->fbdefio = &fb_helper->fbdefio;
ret = fb_deferred_io_init(info);
if (ret)
- goto err_drm_fb_helper_release_info;
+ goto err_vfree;
return 0;
-err_drm_fb_helper_release_info:
- drm_fb_helper_release_info(fb_helper);
err_vfree:
vfree(screen_buffer);
err_drm_client_framebuffer_delete:
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index a379c8ca435a..b24516998755 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -60,18 +60,11 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes,
struct exynos_drm_gem *exynos_gem)
{
- struct fb_info *fbi;
+ struct fb_info *fbi = helper->info;
struct drm_framebuffer *fb = helper->fb;
unsigned int size = fb->width * fb->height * fb->format->cpp[0];
unsigned long offset;
- fbi = drm_fb_helper_alloc_info(helper);
- if (IS_ERR(fbi)) {
- DRM_DEV_ERROR(to_dma_dev(helper->dev),
- "failed to allocate fb info.\n");
- return PTR_ERR(fbi);
- }
-
fbi->fbops = &exynos_drm_fb_ops;
drm_fb_helper_fill_info(fbi, helper, sizes);
diff --git a/drivers/gpu/drm/gma500/fbdev.c b/drivers/gpu/drm/gma500/fbdev.c
index 8e3128298728..d80a18fde1aa 100644
--- a/drivers/gpu/drm/gma500/fbdev.c
+++ b/drivers/gpu/drm/gma500/fbdev.c
@@ -110,7 +110,7 @@ static int psb_fbdev_fb_probe(struct drm_fb_helper *fb_helper,
struct drm_device *dev = fb_helper->dev;
struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct pci_dev *pdev = to_pci_dev(dev->dev);
- struct fb_info *info;
+ struct fb_info *info = fb_helper->info;
struct drm_framebuffer *fb;
struct drm_mode_fb_cmd2 mode_cmd = { };
int size;
@@ -165,12 +165,6 @@ static int psb_fbdev_fb_probe(struct drm_fb_helper *fb_helper,
fb_helper->fb = fb;
- info = drm_fb_helper_alloc_info(fb_helper);
- if (IS_ERR(info)) {
- ret = PTR_ERR(info);
- goto err_drm_framebuffer_unregister_private;
- }
-
info->fbops = &psb_fbdev_fb_ops;
/* Accessed stolen memory directly */
@@ -194,11 +188,6 @@ static int psb_fbdev_fb_probe(struct drm_fb_helper *fb_helper,
return 0;
-err_drm_framebuffer_unregister_private:
- drm_framebuffer_unregister_private(fb);
- fb->obj[0] = NULL;
- drm_framebuffer_cleanup(fb);
- kfree(fb);
err_drm_gem_object_put:
drm_gem_object_put(obj);
return ret;
diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h
index 53e5c33e08c3..8d5366bc8055 100644
--- a/drivers/gpu/drm/i915/display/intel_display_core.h
+++ b/drivers/gpu/drm/i915/display/intel_display_core.h
@@ -267,6 +267,9 @@ struct intel_wm {
};
struct intel_display {
+ /* drm device backpointer */
+ struct drm_device *drm;
+
/* Display functions */
struct {
/* Top level crtc-ish functions */
diff --git a/drivers/gpu/drm/i915/display/intel_display_device.c b/drivers/gpu/drm/i915/display/intel_display_device.c
index c39f8a15d8aa..8ca893606ac9 100644
--- a/drivers/gpu/drm/i915/display/intel_display_device.c
+++ b/drivers/gpu/drm/i915/display/intel_display_device.c
@@ -857,6 +857,9 @@ intel_display_device_probe(struct drm_i915_private *i915, bool has_gmdid,
struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
int i;
+ /* Add drm device backpointer as early as possible. */
+ i915->display.drm = &i915->drm;
+
if (has_gmdid)
return probe_gmdid_display(i915, gmdid_ver, gmdid_rel, gmdid_step);
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 3a228cfb1550..733887787c80 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -2112,4 +2112,44 @@ to_intel_frontbuffer(struct drm_framebuffer *fb)
return fb ? to_intel_framebuffer(fb)->frontbuffer : NULL;
}
+/*
+ * Conversion functions/macros from various pointer types to struct
+ * intel_display pointer.
+ */
+#define __drm_device_to_intel_display(p) \
+ ((p) ? &to_i915(p)->display : NULL)
+#define __device_to_intel_display(p) \
+ __drm_device_to_intel_display(&kdev_to_i915(p)->drm)
+#define __intel_connector_to_intel_display(p) \
+ __drm_device_to_intel_display((p)->base.dev)
+#define __intel_crtc_to_intel_display(p) \
+ __drm_device_to_intel_display((p)->base.dev)
+#define __intel_crtc_state_to_intel_display(p) \
+ __drm_device_to_intel_display((p)->uapi.crtc->dev)
+#define __intel_digital_port_to_intel_display(p) \
+ __drm_device_to_intel_display((p)->base.base.dev)
+#define __intel_dp_to_intel_display(p) \
+ __drm_device_to_intel_display(dp_to_dig_port(p)->base.base.dev)
+#define __intel_encoder_to_intel_display(p) \
+ __drm_device_to_intel_display((p)->base.dev)
+#define __intel_hdmi_to_intel_display(p) \
+ __drm_device_to_intel_display(hdmi_to_dig_port(p)->base.base.dev)
+
+/* Helper for generic association. Map types to conversion functions/macros. */
+#define __assoc(type, p) \
+ struct type: __##type##_to_intel_display((struct type *)(p))
+
+/* Convert various pointer types to struct intel_display pointer. */
+#define to_intel_display(p) \
+ _Generic(*p, \
+ __assoc(drm_device, p), \
+ __assoc(device, p), \
+ __assoc(intel_connector, p), \
+ __assoc(intel_crtc, p), \
+ __assoc(intel_crtc_state, p), \
+ __assoc(intel_digital_port, p), \
+ __assoc(intel_dp, p), \
+ __assoc(intel_encoder, p), \
+ __assoc(intel_hdmi, p))
+
#endif /* __INTEL_DISPLAY_TYPES_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c
index 25382022cd27..a6861c3bd224 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -223,6 +223,11 @@ static u16 intel_fbc_override_cfb_stride(const struct intel_plane_state *plane_s
return 0;
}
+static bool intel_fbc_has_fences(struct drm_i915_private *i915)
+{
+ return intel_gt_support_legacy_fencing(to_gt(i915));
+}
+
static u32 i8xx_fbc_ctl(struct intel_fbc *fbc)
{
const struct intel_fbc_state *fbc_state = &fbc->state;
@@ -608,7 +613,7 @@ static void ivb_fbc_activate(struct intel_fbc *fbc)
else if (DISPLAY_VER(i915) == 9)
skl_fbc_program_cfb_stride(fbc);
- if (intel_gt_support_legacy_fencing(to_gt(i915)))
+ if (intel_fbc_has_fences(i915))
snb_fbc_program_fence(fbc);
intel_de_write(i915, ILK_DPFC_CONTROL(fbc->id),
@@ -992,7 +997,7 @@ static void intel_fbc_update_state(struct intel_atomic_state *state,
fbc_state->fence_y_offset = intel_plane_fence_y_offset(plane_state);
drm_WARN_ON(&i915->drm, plane_state->flags & PLANE_HAS_FENCE &&
- !intel_gt_support_legacy_fencing(to_gt(i915)));
+ !intel_fbc_has_fences(i915));
if (plane_state->flags & PLANE_HAS_FENCE)
fbc_state->fence_id = i915_vma_fence_id(plane_state->ggtt_vma);
diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c
index 31d0d695d567..031e38e919df 100644
--- a/drivers/gpu/drm/i915/display/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/display/intel_fbdev.c
@@ -218,7 +218,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
.type = I915_GTT_VIEW_NORMAL,
};
intel_wakeref_t wakeref;
- struct fb_info *info;
+ struct fb_info *info = helper->info;
struct i915_vma *vma;
unsigned long flags = 0;
bool prealloc = false;
@@ -271,13 +271,6 @@ static int intelfb_create(struct drm_fb_helper *helper,
goto out_unlock;
}
- info = drm_fb_helper_alloc_info(helper);
- if (IS_ERR(info)) {
- drm_err(&dev_priv->drm, "Failed to allocate fb_info (%pe)\n", info);
- ret = PTR_ERR(info);
- goto out_unpin;
- }
-
ifbdev->helper.fb = &ifbdev->fb->base;
info->fbops = &intelfb_ops;
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c
index cb99839afcd0..f377c4484e18 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_hdcp.c
@@ -120,7 +120,7 @@ static
int intel_hdcp_read_valid_bksv(struct intel_digital_port *dig_port,
const struct intel_hdcp_shim *shim, u8 *bksv)
{
- struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ struct intel_display *display = to_intel_display(dig_port);
int ret, i, tries = 2;
/* HDCP spec states that we must retry the bksv if it is invalid */
@@ -132,7 +132,7 @@ int intel_hdcp_read_valid_bksv(struct intel_digital_port *dig_port,
break;
}
if (i == tries) {
- drm_dbg_kms(&i915->drm, "Bksv is invalid\n");
+ drm_dbg_kms(display->drm, "Bksv is invalid\n");
return -ENODEV;
}
@@ -622,15 +622,15 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector,
static
int intel_hdcp_auth_downstream(struct intel_connector *connector)
{
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
const struct intel_hdcp_shim *shim = connector->hdcp.shim;
u8 bstatus[2], num_downstream, *ksv_fifo;
int ret, i, tries = 3;
ret = intel_hdcp_poll_ksv_fifo(dig_port, shim);
if (ret) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"KSV list failed to become ready (%d)\n", ret);
return ret;
}
@@ -641,7 +641,7 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
if (DRM_HDCP_MAX_DEVICE_EXCEEDED(bstatus[0]) ||
DRM_HDCP_MAX_CASCADE_EXCEEDED(bstatus[1])) {
- drm_dbg_kms(&i915->drm, "Max Topology Limit Exceeded\n");
+ drm_dbg_kms(display->drm, "Max Topology Limit Exceeded\n");
return -EPERM;
}
@@ -654,14 +654,14 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
*/
num_downstream = DRM_HDCP_NUM_DOWNSTREAM(bstatus[0]);
if (num_downstream == 0) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"Repeater with zero downstream devices\n");
return -EINVAL;
}
ksv_fifo = kcalloc(DRM_HDCP_KSV_LEN, num_downstream, GFP_KERNEL);
if (!ksv_fifo) {
- drm_dbg_kms(&i915->drm, "Out of mem: ksv_fifo\n");
+ drm_dbg_kms(display->drm, "Out of mem: ksv_fifo\n");
return -ENOMEM;
}
@@ -669,9 +669,9 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
if (ret)
goto err;
- if (drm_hdcp_check_ksvs_revoked(&i915->drm, ksv_fifo,
+ if (drm_hdcp_check_ksvs_revoked(display->drm, ksv_fifo,
num_downstream) > 0) {
- drm_err(&i915->drm, "Revoked Ksv(s) in ksv_fifo\n");
+ drm_err(display->drm, "Revoked Ksv(s) in ksv_fifo\n");
ret = -EPERM;
goto err;
}
@@ -689,12 +689,12 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
}
if (i == tries) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"V Prime validation failed.(%d)\n", ret);
goto err;
}
- drm_dbg_kms(&i915->drm, "HDCP is enabled (%d downstream devices)\n",
+ drm_dbg_kms(display->drm, "HDCP is enabled (%d downstream devices)\n",
num_downstream);
ret = 0;
err:
@@ -1086,9 +1086,9 @@ static void intel_hdcp_prop_work(struct work_struct *work)
struct intel_hdcp *hdcp = container_of(work, struct intel_hdcp,
prop_work);
struct intel_connector *connector = intel_hdcp_to_connector(hdcp);
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct intel_display *display = to_intel_display(connector);
- drm_modeset_lock(&i915->drm.mode_config.connection_mutex, NULL);
+ drm_modeset_lock(&display->drm->mode_config.connection_mutex, NULL);
mutex_lock(&hdcp->mutex);
/*
@@ -1101,7 +1101,7 @@ static void intel_hdcp_prop_work(struct work_struct *work)
hdcp->value);
mutex_unlock(&hdcp->mutex);
- drm_modeset_unlock(&i915->drm.mode_config.connection_mutex);
+ drm_modeset_unlock(&display->drm->mode_config.connection_mutex);
drm_connector_put(&connector->base);
}
@@ -1116,25 +1116,25 @@ static int
hdcp2_prepare_ake_init(struct intel_connector *connector,
struct hdcp2_ake_init *ake_data)
{
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&i915->display.hdcp.hdcp_mutex);
- arbiter = i915->display.hdcp.arbiter;
+ mutex_lock(&display->hdcp.hdcp_mutex);
+ arbiter = display->hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return -EINVAL;
}
ret = arbiter->ops->initiate_hdcp2_session(arbiter->hdcp_dev, data, ake_data);
if (ret)
- drm_dbg_kms(&i915->drm, "Prepare_ake_init failed. %d\n",
+ drm_dbg_kms(display->drm, "Prepare_ake_init failed. %d\n",
ret);
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return ret;
}
@@ -1146,17 +1146,17 @@ hdcp2_verify_rx_cert_prepare_km(struct intel_connector *connector,
struct hdcp2_ake_no_stored_km *ek_pub_km,
size_t *msg_sz)
{
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&i915->display.hdcp.hdcp_mutex);
- arbiter = i915->display.hdcp.arbiter;
+ mutex_lock(&display->hdcp.hdcp_mutex);
+ arbiter = display->hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return -EINVAL;
}
@@ -1164,9 +1164,9 @@ hdcp2_verify_rx_cert_prepare_km(struct intel_connector *connector,
rx_cert, paired,
ek_pub_km, msg_sz);
if (ret < 0)
- drm_dbg_kms(&i915->drm, "Verify rx_cert failed. %d\n",
+ drm_dbg_kms(display->drm, "Verify rx_cert failed. %d\n",
ret);
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return ret;
}
@@ -1174,24 +1174,24 @@ hdcp2_verify_rx_cert_prepare_km(struct intel_connector *connector,
static int hdcp2_verify_hprime(struct intel_connector *connector,
struct hdcp2_ake_send_hprime *rx_hprime)
{
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&i915->display.hdcp.hdcp_mutex);
- arbiter = i915->display.hdcp.arbiter;
+ mutex_lock(&display->hdcp.hdcp_mutex);
+ arbiter = display->hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return -EINVAL;
}
ret = arbiter->ops->verify_hprime(arbiter->hdcp_dev, data, rx_hprime);
if (ret < 0)
- drm_dbg_kms(&i915->drm, "Verify hprime failed. %d\n", ret);
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ drm_dbg_kms(display->drm, "Verify hprime failed. %d\n", ret);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return ret;
}
@@ -1200,25 +1200,25 @@ static int
hdcp2_store_pairing_info(struct intel_connector *connector,
struct hdcp2_ake_send_pairing_info *pairing_info)
{
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&i915->display.hdcp.hdcp_mutex);
- arbiter = i915->display.hdcp.arbiter;
+ mutex_lock(&display->hdcp.hdcp_mutex);
+ arbiter = display->hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return -EINVAL;
}
ret = arbiter->ops->store_pairing_info(arbiter->hdcp_dev, data, pairing_info);
if (ret < 0)
- drm_dbg_kms(&i915->drm, "Store pairing info failed. %d\n",
+ drm_dbg_kms(display->drm, "Store pairing info failed. %d\n",
ret);
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return ret;
}
@@ -1227,25 +1227,25 @@ static int
hdcp2_prepare_lc_init(struct intel_connector *connector,
struct hdcp2_lc_init *lc_init)
{
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&i915->display.hdcp.hdcp_mutex);
- arbiter = i915->display.hdcp.arbiter;
+ mutex_lock(&display->hdcp.hdcp_mutex);
+ arbiter = display->hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return -EINVAL;
}
ret = arbiter->ops->initiate_locality_check(arbiter->hdcp_dev, data, lc_init);
if (ret < 0)
- drm_dbg_kms(&i915->drm, "Prepare lc_init failed. %d\n",
+ drm_dbg_kms(display->drm, "Prepare lc_init failed. %d\n",
ret);
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return ret;
}
@@ -1254,25 +1254,25 @@ static int
hdcp2_verify_lprime(struct intel_connector *connector,
struct hdcp2_lc_send_lprime *rx_lprime)
{
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&i915->display.hdcp.hdcp_mutex);
- arbiter = i915->display.hdcp.arbiter;
+ mutex_lock(&display->hdcp.hdcp_mutex);
+ arbiter = display->hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return -EINVAL;
}
ret = arbiter->ops->verify_lprime(arbiter->hdcp_dev, data, rx_lprime);
if (ret < 0)
- drm_dbg_kms(&i915->drm, "Verify L_Prime failed. %d\n",
+ drm_dbg_kms(display->drm, "Verify L_Prime failed. %d\n",
ret);
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return ret;
}
@@ -1280,25 +1280,25 @@ hdcp2_verify_lprime(struct intel_connector *connector,
static int hdcp2_prepare_skey(struct intel_connector *connector,
struct hdcp2_ske_send_eks *ske_data)
{
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&i915->display.hdcp.hdcp_mutex);
- arbiter = i915->display.hdcp.arbiter;
+ mutex_lock(&display->hdcp.hdcp_mutex);
+ arbiter = display->hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return -EINVAL;
}
ret = arbiter->ops->get_session_key(arbiter->hdcp_dev, data, ske_data);
if (ret < 0)
- drm_dbg_kms(&i915->drm, "Get session key failed. %d\n",
+ drm_dbg_kms(display->drm, "Get session key failed. %d\n",
ret);
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return ret;
}
@@ -1309,17 +1309,17 @@ hdcp2_verify_rep_topology_prepare_ack(struct intel_connector *connector,
*rep_topology,
struct hdcp2_rep_send_ack *rep_send_ack)
{
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&i915->display.hdcp.hdcp_mutex);
- arbiter = i915->display.hdcp.arbiter;
+ mutex_lock(&display->hdcp.hdcp_mutex);
+ arbiter = display->hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return -EINVAL;
}
@@ -1328,9 +1328,9 @@ hdcp2_verify_rep_topology_prepare_ack(struct intel_connector *connector,
rep_topology,
rep_send_ack);
if (ret < 0)
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"Verify rep topology failed. %d\n", ret);
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return ret;
}
@@ -1339,71 +1339,71 @@ static int
hdcp2_verify_mprime(struct intel_connector *connector,
struct hdcp2_rep_stream_ready *stream_ready)
{
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&i915->display.hdcp.hdcp_mutex);
- arbiter = i915->display.hdcp.arbiter;
+ mutex_lock(&display->hdcp.hdcp_mutex);
+ arbiter = display->hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return -EINVAL;
}
ret = arbiter->ops->verify_mprime(arbiter->hdcp_dev, data, stream_ready);
if (ret < 0)
- drm_dbg_kms(&i915->drm, "Verify mprime failed. %d\n", ret);
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ drm_dbg_kms(display->drm, "Verify mprime failed. %d\n", ret);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return ret;
}
static int hdcp2_authenticate_port(struct intel_connector *connector)
{
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&i915->display.hdcp.hdcp_mutex);
- arbiter = i915->display.hdcp.arbiter;
+ mutex_lock(&display->hdcp.hdcp_mutex);
+ arbiter = display->hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return -EINVAL;
}
ret = arbiter->ops->enable_hdcp_authentication(arbiter->hdcp_dev, data);
if (ret < 0)
- drm_dbg_kms(&i915->drm, "Enable hdcp auth failed. %d\n",
+ drm_dbg_kms(display->drm, "Enable hdcp auth failed. %d\n",
ret);
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return ret;
}
static int hdcp2_close_session(struct intel_connector *connector)
{
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct i915_hdcp_arbiter *arbiter;
int ret;
- mutex_lock(&i915->display.hdcp.hdcp_mutex);
- arbiter = i915->display.hdcp.arbiter;
+ mutex_lock(&display->hdcp.hdcp_mutex);
+ arbiter = display->hdcp.arbiter;
if (!arbiter || !arbiter->ops) {
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return -EINVAL;
}
ret = arbiter->ops->close_hdcp_session(arbiter->hdcp_dev,
&dig_port->hdcp_port_data);
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return ret;
}
@@ -1416,8 +1416,8 @@ static int hdcp2_deauthenticate_port(struct intel_connector *connector)
/* Authentication flow starts from here */
static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
{
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
union {
struct hdcp2_ake_init ake_init;
@@ -1449,16 +1449,16 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
return ret;
if (msgs.send_cert.rx_caps[0] != HDCP_2_2_RX_CAPS_VERSION_VAL) {
- drm_dbg_kms(&i915->drm, "cert.rx_caps dont claim HDCP2.2\n");
+ drm_dbg_kms(display->drm, "cert.rx_caps dont claim HDCP2.2\n");
return -EINVAL;
}
hdcp->is_repeater = HDCP_2_2_RX_REPEATER(msgs.send_cert.rx_caps[2]);
- if (drm_hdcp_check_ksvs_revoked(&i915->drm,
+ if (drm_hdcp_check_ksvs_revoked(display->drm,
msgs.send_cert.cert_rx.receiver_id,
1) > 0) {
- drm_err(&i915->drm, "Receiver ID is revoked\n");
+ drm_err(display->drm, "Receiver ID is revoked\n");
return -EPERM;
}
@@ -1611,8 +1611,8 @@ int _hdcp2_propagate_stream_management_info(struct intel_connector *connector)
static
int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
{
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
union {
struct hdcp2_rep_send_receiverid_list recvid_list;
@@ -1632,7 +1632,7 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
if (HDCP_2_2_MAX_CASCADE_EXCEEDED(rx_info[1]) ||
HDCP_2_2_MAX_DEVS_EXCEEDED(rx_info[1])) {
- drm_dbg_kms(&i915->drm, "Topology Max Size Exceeded\n");
+ drm_dbg_kms(display->drm, "Topology Max Size Exceeded\n");
return -EINVAL;
}
@@ -1649,23 +1649,24 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
drm_hdcp_be24_to_cpu((const u8 *)msgs.recvid_list.seq_num_v);
if (!hdcp->hdcp2_encrypted && seq_num_v) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"Non zero Seq_num_v at first RecvId_List msg\n");
return -EINVAL;
}
- if (seq_num_v < hdcp->seq_num_v) {
- /* Roll over of the seq_num_v from repeater. Reauthenticate. */
- drm_dbg_kms(&i915->drm, "Seq_num_v roll over.\n");
+ if (hdcp->hdcp2_encrypted && seq_num_v <= hdcp->seq_num_v) {
+ /* Reauthenticate on Seq_num_v repeat or rollover */
+ drm_dbg_kms(display->drm, "Seq_num_v %s\n",
+ seq_num_v == hdcp->seq_num_v ? "repeat" : "rollover");
return -EINVAL;
}
device_cnt = (HDCP_2_2_DEV_COUNT_HI(rx_info[0]) << 4 |
HDCP_2_2_DEV_COUNT_LO(rx_info[1]));
- if (drm_hdcp_check_ksvs_revoked(&i915->drm,
+ if (drm_hdcp_check_ksvs_revoked(display->drm,
msgs.recvid_list.receiver_ids,
device_cnt) > 0) {
- drm_err(&i915->drm, "Revoked receiver ID(s) is in list\n");
+ drm_err(display->drm, "Revoked receiver ID(s) is in list\n");
return -EPERM;
}
@@ -1686,28 +1687,28 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
static int hdcp2_authenticate_sink(struct intel_connector *connector)
{
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
const struct intel_hdcp_shim *shim = hdcp->shim;
int ret;
ret = hdcp2_authentication_key_exchange(connector);
if (ret < 0) {
- drm_dbg_kms(&i915->drm, "AKE Failed. Err : %d\n", ret);
+ drm_dbg_kms(display->drm, "AKE Failed. Err : %d\n", ret);
return ret;
}
ret = hdcp2_locality_check(connector);
if (ret < 0) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"Locality Check failed. Err : %d\n", ret);
return ret;
}
ret = hdcp2_session_key_exchange(connector);
if (ret < 0) {
- drm_dbg_kms(&i915->drm, "SKE Failed. Err : %d\n", ret);
+ drm_dbg_kms(display->drm, "SKE Failed. Err : %d\n", ret);
return ret;
}
@@ -1722,7 +1723,7 @@ static int hdcp2_authenticate_sink(struct intel_connector *connector)
if (hdcp->is_repeater) {
ret = hdcp2_authenticate_repeater_topology(connector);
if (ret < 0) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"Repeater Auth Failed. Err: %d\n", ret);
return ret;
}
@@ -1851,7 +1852,7 @@ static int hdcp2_disable_encryption(struct intel_connector *connector)
static int
hdcp2_propagate_stream_management_info(struct intel_connector *connector)
{
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct intel_display *display = to_intel_display(connector);
int i, tries = 3, ret;
if (!connector->hdcp.is_repeater)
@@ -1864,12 +1865,12 @@ hdcp2_propagate_stream_management_info(struct intel_connector *connector)
/* Lets restart the auth incase of seq_num_m roll over */
if (connector->hdcp.seq_num_m > HDCP_2_2_SEQ_NUM_MAX) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"seq_num_m roll over.(%d)\n", ret);
break;
}
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"HDCP2 stream management %d of %d Failed.(%d)\n",
i + 1, tries, ret);
}
@@ -1879,8 +1880,8 @@ hdcp2_propagate_stream_management_info(struct intel_connector *connector)
static int hdcp2_authenticate_and_encrypt(struct intel_connector *connector)
{
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
int ret = 0, i, tries = 3;
for (i = 0; i < tries && !dig_port->hdcp_auth_status; i++) {
@@ -1890,7 +1891,7 @@ static int hdcp2_authenticate_and_encrypt(struct intel_connector *connector)
ret = hdcp2_propagate_stream_management_info(connector);
if (ret) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"Stream management failed.(%d)\n",
ret);
break;
@@ -1899,15 +1900,15 @@ static int hdcp2_authenticate_and_encrypt(struct intel_connector *connector)
ret = hdcp2_authenticate_port(connector);
if (!ret)
break;
- drm_dbg_kms(&i915->drm, "HDCP2 port auth failed.(%d)\n",
+ drm_dbg_kms(display->drm, "HDCP2 port auth failed.(%d)\n",
ret);
}
/* Clearing the mei hdcp session */
- drm_dbg_kms(&i915->drm, "HDCP2.2 Auth %d of %d Failed.(%d)\n",
+ drm_dbg_kms(display->drm, "HDCP2.2 Auth %d of %d Failed.(%d)\n",
i + 1, tries, ret);
if (hdcp2_deauthenticate_port(connector) < 0)
- drm_dbg_kms(&i915->drm, "Port deauth failed.\n");
+ drm_dbg_kms(display->drm, "Port deauth failed.\n");
}
if (!ret && !dig_port->hdcp_auth_status) {
@@ -1918,10 +1919,10 @@ static int hdcp2_authenticate_and_encrypt(struct intel_connector *connector)
msleep(HDCP_2_2_DELAY_BEFORE_ENCRYPTION_EN);
ret = hdcp2_enable_encryption(connector);
if (ret < 0) {
- drm_dbg_kms(&i915->drm,
+ drm_dbg_kms(display->drm,
"Encryption Enable Failed.(%d)\n", ret);
if (hdcp2_deauthenticate_port(connector) < 0)
- drm_dbg_kms(&i915->drm, "Port deauth failed.\n");
+ drm_dbg_kms(display->drm, "Port deauth failed.\n");
}
}
@@ -1933,22 +1934,22 @@ static int hdcp2_authenticate_and_encrypt(struct intel_connector *connector)
static int _intel_hdcp2_enable(struct intel_connector *connector)
{
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct intel_display *display = to_intel_display(connector);
struct intel_hdcp *hdcp = &connector->hdcp;
int ret;
- drm_dbg_kms(&i915->drm, "[%s:%d] HDCP2.2 is being enabled. Type: %d\n",
+ drm_dbg_kms(display->drm, "[%s:%d] HDCP2.2 is being enabled. Type: %d\n",
connector->base.name, connector->base.base.id,
hdcp->content_type);
ret = hdcp2_authenticate_and_encrypt(connector);
if (ret) {
- drm_dbg_kms(&i915->drm, "HDCP2 Type%d Enabling Failed. (%d)\n",
+ drm_dbg_kms(display->drm, "HDCP2 Type%d Enabling Failed. (%d)\n",
hdcp->content_type, ret);
return ret;
}
- drm_dbg_kms(&i915->drm, "[%s:%d] HDCP2.2 is enabled. Type %d\n",
+ drm_dbg_kms(display->drm, "[%s:%d] HDCP2.2 is enabled. Type %d\n",
connector->base.name, connector->base.base.id,
hdcp->content_type);
@@ -1959,23 +1960,23 @@ static int _intel_hdcp2_enable(struct intel_connector *connector)
static int
_intel_hdcp2_disable(struct intel_connector *connector, bool hdcp2_link_recovery)
{
+ struct intel_display *display = to_intel_display(connector);
struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct hdcp_port_data *data = &dig_port->hdcp_port_data;
struct intel_hdcp *hdcp = &connector->hdcp;
int ret;
- drm_dbg_kms(&i915->drm, "[%s:%d] HDCP2.2 is being Disabled\n",
+ drm_dbg_kms(display->drm, "[%s:%d] HDCP2.2 is being Disabled\n",
connector->base.name, connector->base.base.id);
if (hdcp->shim->stream_2_2_encryption) {
ret = hdcp->shim->stream_2_2_encryption(connector, false);
if (ret) {
- drm_err(&i915->drm, "[%s:%d] Failed to disable HDCP 2.2 stream enc\n",
+ drm_err(display->drm, "[%s:%d] Failed to disable HDCP 2.2 stream enc\n",
connector->base.name, connector->base.base.id);
return ret;
}
- drm_dbg_kms(&i915->drm, "HDCP 2.2 transcoder: %s stream encryption disabled\n",
+ drm_dbg_kms(display->drm, "HDCP 2.2 transcoder: %s stream encryption disabled\n",
transcoder_name(hdcp->stream_transcoder));
if (dig_port->num_hdcp_streams > 0 && !hdcp2_link_recovery)
@@ -1985,7 +1986,7 @@ _intel_hdcp2_disable(struct intel_connector *connector, bool hdcp2_link_recovery
ret = hdcp2_disable_encryption(connector);
if (hdcp2_deauthenticate_port(connector) < 0)
- drm_dbg_kms(&i915->drm, "Port deauth failed.\n");
+ drm_dbg_kms(display->drm, "Port deauth failed.\n");
connector->hdcp.hdcp2_encrypted = false;
dig_port->hdcp_auth_status = false;
@@ -2108,29 +2109,29 @@ static void intel_hdcp_check_work(struct work_struct *work)
DRM_HDCP_CHECK_PERIOD_MS);
}
-static int i915_hdcp_component_bind(struct device *i915_kdev,
+static int i915_hdcp_component_bind(struct device *drv_kdev,
struct device *mei_kdev, void *data)
{
- struct drm_i915_private *i915 = kdev_to_i915(i915_kdev);
+ struct intel_display *display = to_intel_display(drv_kdev);
- drm_dbg(&i915->drm, "I915 HDCP comp bind\n");
- mutex_lock(&i915->display.hdcp.hdcp_mutex);
- i915->display.hdcp.arbiter = (struct i915_hdcp_arbiter *)data;
- i915->display.hdcp.arbiter->hdcp_dev = mei_kdev;
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ drm_dbg(display->drm, "I915 HDCP comp bind\n");
+ mutex_lock(&display->hdcp.hdcp_mutex);
+ display->hdcp.arbiter = (struct i915_hdcp_arbiter *)data;
+ display->hdcp.arbiter->hdcp_dev = mei_kdev;
+ mutex_unlock(&display->hdcp.hdcp_mutex);
return 0;
}
-static void i915_hdcp_component_unbind(struct device *i915_kdev,
+static void i915_hdcp_component_unbind(struct device *drv_kdev,
struct device *mei_kdev, void *data)
{
- struct drm_i915_private *i915 = kdev_to_i915(i915_kdev);
+ struct intel_display *display = to_intel_display(drv_kdev);
- drm_dbg(&i915->drm, "I915 HDCP comp unbind\n");
- mutex_lock(&i915->display.hdcp.hdcp_mutex);
- i915->display.hdcp.arbiter = NULL;
- mutex_unlock(&i915->display.hdcp.hdcp_mutex);
+ drm_dbg(display->drm, "I915 HDCP comp unbind\n");
+ mutex_lock(&display->hdcp.hdcp_mutex);
+ display->hdcp.arbiter = NULL;
+ mutex_unlock(&display->hdcp.hdcp_mutex);
}
static const struct component_ops i915_hdcp_ops = {
@@ -2245,13 +2246,13 @@ static void intel_hdcp2_init(struct intel_connector *connector,
struct intel_digital_port *dig_port,
const struct intel_hdcp_shim *shim)
{
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct intel_display *display = to_intel_display(connector);
struct intel_hdcp *hdcp = &connector->hdcp;
int ret;
ret = initialize_hdcp_port_data(connector, dig_port, shim);
if (ret) {
- drm_dbg_kms(&i915->drm, "Mei hdcp data init failed\n");
+ drm_dbg_kms(display->drm, "Mei hdcp data init failed\n");
return;
}
@@ -2320,6 +2321,9 @@ intel_hdcp_set_streams(struct intel_digital_port *dig_port,
if (conn_dig_port != dig_port)
continue;
+ if (drm_WARN_ON(&i915->drm, data->k >= INTEL_NUM_PIPES(i915)))
+ return -EINVAL;
+
data->streams[data->k].stream_id =
intel_conn_to_vcpi(&state->base, connector);
data->k++;
@@ -2330,7 +2334,7 @@ intel_hdcp_set_streams(struct intel_digital_port *dig_port,
}
drm_connector_list_iter_end(&conn_iter);
- if (drm_WARN_ON(&i915->drm, data->k > INTEL_NUM_PIPES(i915) || data->k == 0))
+ if (drm_WARN_ON(&i915->drm, !data->k))
return -EINVAL;
return 0;
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
index b844bdd16de9..0082b822a30e 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -16,6 +16,9 @@ bool intel_vrr_is_capable(struct intel_connector *connector)
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_dp *intel_dp;
+ if (!HAS_VRR(i915))
+ return false;
+
/*
* DP Sink is capable of VRR video timings if
* Ignore MSA bit is set in DPCD.
@@ -38,8 +41,11 @@ bool intel_vrr_is_capable(struct intel_connector *connector)
return false;
}
- return HAS_VRR(i915) &&
- info->monitor_range.max_vfreq - info->monitor_range.min_vfreq > 10;
+ if (!info->monitor_range.min_vfreq || !info->monitor_range.max_vfreq ||
+ info->monitor_range.min_vfreq > info->monitor_range.max_vfreq)
+ return false;
+
+ return info->monitor_range.max_vfreq - info->monitor_range.min_vfreq > 10;
}
void
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
index 036028b8f524..5d3b235fe129 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
@@ -494,6 +494,7 @@ static void mtk_disp_ovl_adaptor_master_unbind(struct device *dev)
struct mtk_disp_ovl_adaptor *priv = dev_get_drvdata(dev);
priv->children_bound = false;
+ component_unbind_all(dev, priv->mmsys_dev);
}
static const struct component_master_ops mtk_disp_ovl_adaptor_master_ops = {
@@ -520,12 +521,15 @@ static int mtk_disp_ovl_adaptor_probe(struct platform_device *pdev)
priv->mmsys_dev = pdev->dev.platform_data;
- component_master_add_with_match(dev, &mtk_disp_ovl_adaptor_master_ops, match);
+ ret = component_master_add_with_match(dev, &mtk_disp_ovl_adaptor_master_ops, match);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to add component master\n");
pm_runtime_enable(dev);
ret = component_add(dev, &mtk_disp_ovl_adaptor_comp_ops);
if (ret != 0) {
+ component_master_del(dev, &mtk_disp_ovl_adaptor_master_ops);
pm_runtime_disable(dev);
dev_err(dev, "Failed to add component: %d\n", ret);
}
@@ -535,6 +539,7 @@ static int mtk_disp_ovl_adaptor_probe(struct platform_device *pdev)
static int mtk_disp_ovl_adaptor_remove(struct platform_device *pdev)
{
+ component_del(&pdev->dev, &mtk_disp_ovl_adaptor_comp_ops);
component_master_del(&pdev->dev, &mtk_disp_ovl_adaptor_master_ops);
pm_runtime_disable(&pdev->dev);
return 0;
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 659112da47b6..859dffe45137 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -185,10 +185,10 @@ static void mtk_drm_crtc_reset(struct drm_crtc *crtc)
{
struct mtk_crtc_state *state;
- if (crtc->state)
+ if (crtc->state) {
__drm_atomic_helper_crtc_destroy_state(crtc->state);
-
- kfree(to_mtk_crtc_state(crtc->state));
+ kfree(to_mtk_crtc_state(crtc->state));
+ }
crtc->state = NULL;
state = kzalloc(sizeof(*state), GFP_KERNEL);
diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c
index 030bedac632d..174a116fba2b 100644
--- a/drivers/gpu/drm/msm/msm_fbdev.c
+++ b/drivers/gpu/drm/msm/msm_fbdev.c
@@ -70,9 +70,9 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
{
struct drm_device *dev = helper->dev;
struct msm_drm_private *priv = dev->dev_private;
+ struct fb_info *fbi = helper->info;
struct drm_framebuffer *fb = NULL;
struct drm_gem_object *bo;
- struct fb_info *fbi = NULL;
uint64_t paddr;
uint32_t format;
int ret, pitch;
@@ -105,13 +105,6 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
goto fail;
}
- fbi = drm_fb_helper_alloc_info(helper);
- if (IS_ERR(fbi)) {
- DRM_DEV_ERROR(dev->dev, "failed to allocate fb info\n");
- ret = PTR_ERR(fbi);
- goto fail;
- }
-
DBG("fbi=%p, dev=%p", fbi, dev);
helper->fb = fb;
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c
index 523be34682ca..483dc30d7840 100644
--- a/drivers/gpu/drm/omapdrm/omap_fbdev.c
+++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c
@@ -131,9 +131,9 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
struct omap_fbdev *fbdev = to_omap_fbdev(helper);
struct drm_device *dev = helper->dev;
struct omap_drm_private *priv = dev->dev_private;
+ struct fb_info *fbi = helper->info;
struct drm_framebuffer *fb = NULL;
union omap_gem_size gsize;
- struct fb_info *fbi = NULL;
struct drm_mode_fb_cmd2 mode_cmd = {0};
struct drm_gem_object *bo;
dma_addr_t dma_addr;
@@ -199,13 +199,6 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
goto fail;
}
- fbi = drm_fb_helper_alloc_info(helper);
- if (IS_ERR(fbi)) {
- dev_err(dev->dev, "failed to allocate fb info\n");
- ret = PTR_ERR(fbi);
- goto fail;
- }
-
DBG("fbi=%p, dev=%p", fbi, dev);
helper->fb = fb;
diff --git a/drivers/gpu/drm/radeon/radeon_fbdev.c b/drivers/gpu/drm/radeon/radeon_fbdev.c
index fb70de29545c..1101b5feb67d 100644
--- a/drivers/gpu/drm/radeon/radeon_fbdev.c
+++ b/drivers/gpu/drm/radeon/radeon_fbdev.c
@@ -207,7 +207,7 @@ static int radeon_fbdev_fb_helper_fb_probe(struct drm_fb_helper *fb_helper,
{
struct radeon_device *rdev = fb_helper->dev->dev_private;
struct drm_mode_fb_cmd2 mode_cmd = { };
- struct fb_info *info;
+ struct fb_info *info = fb_helper->info;
struct drm_gem_object *gobj;
struct radeon_bo *rbo;
struct drm_framebuffer *fb;
@@ -245,13 +245,6 @@ static int radeon_fbdev_fb_helper_fb_probe(struct drm_fb_helper *fb_helper,
/* setup helper */
fb_helper->fb = fb;
- /* okay we have an object now allocate the framebuffer */
- info = drm_fb_helper_alloc_info(fb_helper);
- if (IS_ERR(info)) {
- ret = PTR_ERR(info);
- goto err_drm_framebuffer_unregister_private;
- }
-
info->fbops = &radeon_fbdev_fb_ops;
/* radeon resume is fragile and needs a vt switch to help it along */
@@ -277,10 +270,6 @@ static int radeon_fbdev_fb_helper_fb_probe(struct drm_fb_helper *fb_helper,
return 0;
-err_drm_framebuffer_unregister_private:
- fb_helper->fb = NULL;
- drm_framebuffer_unregister_private(fb);
- drm_framebuffer_cleanup(fb);
err_kfree:
kfree(fb);
err_radeon_fbdev_destroy_pinned_object:
diff --git a/drivers/gpu/drm/renesas/Kconfig b/drivers/gpu/drm/renesas/Kconfig
index 3777dad17f81..21862a8ef710 100644
--- a/drivers/gpu/drm/renesas/Kconfig
+++ b/drivers/gpu/drm/renesas/Kconfig
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
source "drivers/gpu/drm/renesas/rcar-du/Kconfig"
+source "drivers/gpu/drm/renesas/rz-du/Kconfig"
source "drivers/gpu/drm/renesas/shmobile/Kconfig"
diff --git a/drivers/gpu/drm/renesas/Makefile b/drivers/gpu/drm/renesas/Makefile
index ec0e89e7a592..b8d8bc53967f 100644
--- a/drivers/gpu/drm/renesas/Makefile
+++ b/drivers/gpu/drm/renesas/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
obj-y += rcar-du/
+obj-y += rz-du/
obj-$(CONFIG_DRM_SHMOBILE) += shmobile/
diff --git a/drivers/gpu/drm/renesas/rcar-du/Kconfig b/drivers/gpu/drm/renesas/rcar-du/Kconfig
index 53c356aed5d5..39af73cf2092 100644
--- a/drivers/gpu/drm/renesas/rcar-du/Kconfig
+++ b/drivers/gpu/drm/renesas/rcar-du/Kconfig
@@ -60,14 +60,6 @@ config DRM_RCAR_MIPI_DSI
select DRM_MIPI_DSI
select RESET_CONTROLLER
-config DRM_RZG2L_MIPI_DSI
- tristate "RZ/G2L MIPI DSI Encoder Support"
- depends on DRM && DRM_BRIDGE && OF
- depends on ARCH_RENESAS || COMPILE_TEST
- select DRM_MIPI_DSI
- help
- Enable support for the RZ/G2L Display Unit embedded MIPI DSI encoders.
-
config DRM_RCAR_VSP
bool "R-Car DU VSP Compositor Support" if ARM
default y if ARM64
diff --git a/drivers/gpu/drm/renesas/rcar-du/Makefile b/drivers/gpu/drm/renesas/rcar-du/Makefile
index b8f2c82651d9..6f132325c8b7 100644
--- a/drivers/gpu/drm/renesas/rcar-du/Makefile
+++ b/drivers/gpu/drm/renesas/rcar-du/Makefile
@@ -14,5 +14,3 @@ obj-$(CONFIG_DRM_RCAR_DU) += rcar-du-drm.o
obj-$(CONFIG_DRM_RCAR_DW_HDMI) += rcar_dw_hdmi.o
obj-$(CONFIG_DRM_RCAR_LVDS) += rcar_lvds.o
obj-$(CONFIG_DRM_RCAR_MIPI_DSI) += rcar_mipi_dsi.o
-
-obj-$(CONFIG_DRM_RZG2L_MIPI_DSI) += rzg2l_mipi_dsi.o
diff --git a/drivers/gpu/drm/renesas/rcar-du/rzg2l_mipi_dsi.c b/drivers/gpu/drm/renesas/rcar-du/rzg2l_mipi_dsi.c
deleted file mode 100644
index 6cec796dd463..000000000000
--- a/drivers/gpu/drm/renesas/rcar-du/rzg2l_mipi_dsi.c
+++ /dev/null
@@ -1,816 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * RZ/G2L MIPI DSI Encoder Driver
- *
- * Copyright (C) 2022 Renesas Electronics Corporation
- */
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_graph.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/reset.h>
-#include <linux/slab.h>
-
-#include <drm/drm_atomic.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_bridge.h>
-#include <drm/drm_mipi_dsi.h>
-#include <drm/drm_of.h>
-#include <drm/drm_panel.h>
-#include <drm/drm_probe_helper.h>
-
-#include "rzg2l_mipi_dsi_regs.h"
-
-struct rzg2l_mipi_dsi {
- struct device *dev;
- void __iomem *mmio;
-
- struct reset_control *rstc;
- struct reset_control *arstc;
- struct reset_control *prstc;
-
- struct mipi_dsi_host host;
- struct drm_bridge bridge;
- struct drm_bridge *next_bridge;
-
- struct clk *vclk;
-
- enum mipi_dsi_pixel_format format;
- unsigned int num_data_lanes;
- unsigned int lanes;
- unsigned long mode_flags;
-};
-
-static inline struct rzg2l_mipi_dsi *
-bridge_to_rzg2l_mipi_dsi(struct drm_bridge *bridge)
-{
- return container_of(bridge, struct rzg2l_mipi_dsi, bridge);
-}
-
-static inline struct rzg2l_mipi_dsi *
-host_to_rzg2l_mipi_dsi(struct mipi_dsi_host *host)
-{
- return container_of(host, struct rzg2l_mipi_dsi, host);
-}
-
-struct rzg2l_mipi_dsi_timings {
- unsigned long hsfreq_max;
- u32 t_init;
- u32 tclk_prepare;
- u32 ths_prepare;
- u32 tclk_zero;
- u32 tclk_pre;
- u32 tclk_post;
- u32 tclk_trail;
- u32 ths_zero;
- u32 ths_trail;
- u32 ths_exit;
- u32 tlpx;
-};
-
-static const struct rzg2l_mipi_dsi_timings rzg2l_mipi_dsi_global_timings[] = {
- {
- .hsfreq_max = 80000,
- .t_init = 79801,
- .tclk_prepare = 8,
- .ths_prepare = 13,
- .tclk_zero = 33,
- .tclk_pre = 24,
- .tclk_post = 94,
- .tclk_trail = 10,
- .ths_zero = 23,
- .ths_trail = 17,
- .ths_exit = 13,
- .tlpx = 6,
- },
- {
- .hsfreq_max = 125000,
- .t_init = 79801,
- .tclk_prepare = 8,
- .ths_prepare = 12,
- .tclk_zero = 33,
- .tclk_pre = 15,
- .tclk_post = 94,
- .tclk_trail = 10,
- .ths_zero = 23,
- .ths_trail = 17,
- .ths_exit = 13,
- .tlpx = 6,
- },
- {
- .hsfreq_max = 250000,
- .t_init = 79801,
- .tclk_prepare = 8,
- .ths_prepare = 12,
- .tclk_zero = 33,
- .tclk_pre = 13,
- .tclk_post = 94,
- .tclk_trail = 10,
- .ths_zero = 23,
- .ths_trail = 16,
- .ths_exit = 13,
- .tlpx = 6,
- },
- {
- .hsfreq_max = 360000,
- .t_init = 79801,
- .tclk_prepare = 8,
- .ths_prepare = 10,
- .tclk_zero = 33,
- .tclk_pre = 4,
- .tclk_post = 35,
- .tclk_trail = 7,
- .ths_zero = 16,
- .ths_trail = 9,
- .ths_exit = 13,
- .tlpx = 6,
- },
- {
- .hsfreq_max = 720000,
- .t_init = 79801,
- .tclk_prepare = 8,
- .ths_prepare = 9,
- .tclk_zero = 33,
- .tclk_pre = 4,
- .tclk_post = 35,
- .tclk_trail = 7,
- .ths_zero = 16,
- .ths_trail = 9,
- .ths_exit = 13,
- .tlpx = 6,
- },
- {
- .hsfreq_max = 1500000,
- .t_init = 79801,
- .tclk_prepare = 8,
- .ths_prepare = 9,
- .tclk_zero = 33,
- .tclk_pre = 4,
- .tclk_post = 35,
- .tclk_trail = 7,
- .ths_zero = 16,
- .ths_trail = 9,
- .ths_exit = 13,
- .tlpx = 6,
- },
-};
-
-static void rzg2l_mipi_dsi_phy_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data)
-{
- iowrite32(data, dsi->mmio + reg);
-}
-
-static void rzg2l_mipi_dsi_link_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data)
-{
- iowrite32(data, dsi->mmio + LINK_REG_OFFSET + reg);
-}
-
-static u32 rzg2l_mipi_dsi_phy_read(struct rzg2l_mipi_dsi *dsi, u32 reg)
-{
- return ioread32(dsi->mmio + reg);
-}
-
-static u32 rzg2l_mipi_dsi_link_read(struct rzg2l_mipi_dsi *dsi, u32 reg)
-{
- return ioread32(dsi->mmio + LINK_REG_OFFSET + reg);
-}
-
-/* -----------------------------------------------------------------------------
- * Hardware Setup
- */
-
-static int rzg2l_mipi_dsi_dphy_init(struct rzg2l_mipi_dsi *dsi,
- unsigned long hsfreq)
-{
- const struct rzg2l_mipi_dsi_timings *dphy_timings;
- unsigned int i;
- u32 dphyctrl0;
- u32 dphytim0;
- u32 dphytim1;
- u32 dphytim2;
- u32 dphytim3;
- int ret;
-
- /* All DSI global operation timings are set with recommended setting */
- for (i = 0; i < ARRAY_SIZE(rzg2l_mipi_dsi_global_timings); ++i) {
- dphy_timings = &rzg2l_mipi_dsi_global_timings[i];
- if (hsfreq <= dphy_timings->hsfreq_max)
- break;
- }
-
- /* Initializing DPHY before accessing LINK */
- dphyctrl0 = DSIDPHYCTRL0_CAL_EN_HSRX_OFS | DSIDPHYCTRL0_CMN_MASTER_EN |
- DSIDPHYCTRL0_RE_VDD_DETVCCQLV18 | DSIDPHYCTRL0_EN_BGR;
-
- rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);
- usleep_range(20, 30);
-
- dphyctrl0 |= DSIDPHYCTRL0_EN_LDO1200;
- rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);
- usleep_range(10, 20);
-
- dphytim0 = DSIDPHYTIM0_TCLK_MISS(0) |
- DSIDPHYTIM0_T_INIT(dphy_timings->t_init);
- dphytim1 = DSIDPHYTIM1_THS_PREPARE(dphy_timings->ths_prepare) |
- DSIDPHYTIM1_TCLK_PREPARE(dphy_timings->tclk_prepare) |
- DSIDPHYTIM1_THS_SETTLE(0) |
- DSIDPHYTIM1_TCLK_SETTLE(0);
- dphytim2 = DSIDPHYTIM2_TCLK_TRAIL(dphy_timings->tclk_trail) |
- DSIDPHYTIM2_TCLK_POST(dphy_timings->tclk_post) |
- DSIDPHYTIM2_TCLK_PRE(dphy_timings->tclk_pre) |
- DSIDPHYTIM2_TCLK_ZERO(dphy_timings->tclk_zero);
- dphytim3 = DSIDPHYTIM3_TLPX(dphy_timings->tlpx) |
- DSIDPHYTIM3_THS_EXIT(dphy_timings->ths_exit) |
- DSIDPHYTIM3_THS_TRAIL(dphy_timings->ths_trail) |
- DSIDPHYTIM3_THS_ZERO(dphy_timings->ths_zero);
-
- rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM0, dphytim0);
- rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM1, dphytim1);
- rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM2, dphytim2);
- rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM3, dphytim3);
-
- ret = reset_control_deassert(dsi->rstc);
- if (ret < 0)
- return ret;
-
- udelay(1);
-
- return 0;
-}
-
-static void rzg2l_mipi_dsi_dphy_exit(struct rzg2l_mipi_dsi *dsi)
-{
- u32 dphyctrl0;
-
- dphyctrl0 = rzg2l_mipi_dsi_phy_read(dsi, DSIDPHYCTRL0);
-
- dphyctrl0 &= ~(DSIDPHYCTRL0_EN_LDO1200 | DSIDPHYCTRL0_EN_BGR);
- rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);
-
- reset_control_assert(dsi->rstc);
-}
-
-static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
- const struct drm_display_mode *mode)
-{
- unsigned long hsfreq;
- unsigned int bpp;
- u32 txsetr;
- u32 clstptsetr;
- u32 lptrnstsetr;
- u32 clkkpt;
- u32 clkbfht;
- u32 clkstpt;
- u32 golpbkt;
- int ret;
-
- /*
- * Relationship between hsclk and vclk must follow
- * vclk * bpp = hsclk * 8 * lanes
- * where vclk: video clock (Hz)
- * bpp: video pixel bit depth
- * hsclk: DSI HS Byte clock frequency (Hz)
- * lanes: number of data lanes
- *
- * hsclk(bit) = hsclk(byte) * 8
- */
- bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
- hsfreq = (mode->clock * bpp * 8) / (8 * dsi->lanes);
-
- ret = pm_runtime_resume_and_get(dsi->dev);
- if (ret < 0)
- return ret;
-
- clk_set_rate(dsi->vclk, mode->clock * 1000);
-
- ret = rzg2l_mipi_dsi_dphy_init(dsi, hsfreq);
- if (ret < 0)
- goto err_phy;
-
- /* Enable Data lanes and Clock lanes */
- txsetr = TXSETR_DLEN | TXSETR_NUMLANEUSE(dsi->lanes - 1) | TXSETR_CLEN;
- rzg2l_mipi_dsi_link_write(dsi, TXSETR, txsetr);
-
- /*
- * Global timings characteristic depends on high speed Clock Frequency
- * Currently MIPI DSI-IF just supports maximum FHD@60 with:
- * - videoclock = 148.5 (MHz)
- * - bpp: maximum 24bpp
- * - data lanes: maximum 4 lanes
- * Therefore maximum hsclk will be 891 Mbps.
- */
- if (hsfreq > 445500) {
- clkkpt = 12;
- clkbfht = 15;
- clkstpt = 48;
- golpbkt = 75;
- } else if (hsfreq > 250000) {
- clkkpt = 7;
- clkbfht = 8;
- clkstpt = 27;
- golpbkt = 40;
- } else {
- clkkpt = 8;
- clkbfht = 6;
- clkstpt = 24;
- golpbkt = 29;
- }
-
- clstptsetr = CLSTPTSETR_CLKKPT(clkkpt) | CLSTPTSETR_CLKBFHT(clkbfht) |
- CLSTPTSETR_CLKSTPT(clkstpt);
- rzg2l_mipi_dsi_link_write(dsi, CLSTPTSETR, clstptsetr);
-
- lptrnstsetr = LPTRNSTSETR_GOLPBKT(golpbkt);
- rzg2l_mipi_dsi_link_write(dsi, LPTRNSTSETR, lptrnstsetr);
-
- return 0;
-
-err_phy:
- rzg2l_mipi_dsi_dphy_exit(dsi);
- pm_runtime_put(dsi->dev);
-
- return ret;
-}
-
-static void rzg2l_mipi_dsi_stop(struct rzg2l_mipi_dsi *dsi)
-{
- rzg2l_mipi_dsi_dphy_exit(dsi);
- pm_runtime_put(dsi->dev);
-}
-
-static void rzg2l_mipi_dsi_set_display_timing(struct rzg2l_mipi_dsi *dsi,
- const struct drm_display_mode *mode)
-{
- u32 vich1ppsetr;
- u32 vich1vssetr;
- u32 vich1vpsetr;
- u32 vich1hssetr;
- u32 vich1hpsetr;
- int dsi_format;
- u32 delay[2];
- u8 index;
-
- /* Configuration for Pixel Packet */
- dsi_format = mipi_dsi_pixel_format_to_bpp(dsi->format);
- switch (dsi_format) {
- case 24:
- vich1ppsetr = VICH1PPSETR_DT_RGB24;
- break;
- case 18:
- vich1ppsetr = VICH1PPSETR_DT_RGB18;
- break;
- }
-
- if ((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) &&
- !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST))
- vich1ppsetr |= VICH1PPSETR_TXESYNC_PULSE;
-
- rzg2l_mipi_dsi_link_write(dsi, VICH1PPSETR, vich1ppsetr);
-
- /* Configuration for Video Parameters */
- vich1vssetr = VICH1VSSETR_VACTIVE(mode->vdisplay) |
- VICH1VSSETR_VSA(mode->vsync_end - mode->vsync_start);
- vich1vssetr |= (mode->flags & DRM_MODE_FLAG_PVSYNC) ?
- VICH1VSSETR_VSPOL_HIGH : VICH1VSSETR_VSPOL_LOW;
-
- vich1vpsetr = VICH1VPSETR_VFP(mode->vsync_start - mode->vdisplay) |
- VICH1VPSETR_VBP(mode->vtotal - mode->vsync_end);
-
- vich1hssetr = VICH1HSSETR_HACTIVE(mode->hdisplay) |
- VICH1HSSETR_HSA(mode->hsync_end - mode->hsync_start);
- vich1hssetr |= (mode->flags & DRM_MODE_FLAG_PHSYNC) ?
- VICH1HSSETR_HSPOL_HIGH : VICH1HSSETR_HSPOL_LOW;
-
- vich1hpsetr = VICH1HPSETR_HFP(mode->hsync_start - mode->hdisplay) |
- VICH1HPSETR_HBP(mode->htotal - mode->hsync_end);
-
- rzg2l_mipi_dsi_link_write(dsi, VICH1VSSETR, vich1vssetr);
- rzg2l_mipi_dsi_link_write(dsi, VICH1VPSETR, vich1vpsetr);
- rzg2l_mipi_dsi_link_write(dsi, VICH1HSSETR, vich1hssetr);
- rzg2l_mipi_dsi_link_write(dsi, VICH1HPSETR, vich1hpsetr);
-
- /*
- * Configuration for Delay Value
- * Delay value based on 2 ranges of video clock.
- * 74.25MHz is videoclock of HD@60p or FHD@30p
- */
- if (mode->clock > 74250) {
- delay[0] = 231;
- delay[1] = 216;
- } else {
- delay[0] = 220;
- delay[1] = 212;
- }
-
- if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
- index = 0;
- else
- index = 1;
-
- rzg2l_mipi_dsi_link_write(dsi, VICH1SET1R,
- VICH1SET1R_DLY(delay[index]));
-}
-
-static int rzg2l_mipi_dsi_start_hs_clock(struct rzg2l_mipi_dsi *dsi)
-{
- bool is_clk_cont;
- u32 hsclksetr;
- u32 status;
- int ret;
-
- is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS);
-
- /* Start HS clock */
- hsclksetr = HSCLKSETR_HSCLKRUN_HS | (is_clk_cont ?
- HSCLKSETR_HSCLKMODE_CONT :
- HSCLKSETR_HSCLKMODE_NON_CONT);
- rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR, hsclksetr);
-
- if (is_clk_cont) {
- ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
- status & PLSR_CLLP2HS,
- 2000, 20000, false, dsi, PLSR);
- if (ret < 0) {
- dev_err(dsi->dev, "failed to start HS clock\n");
- return ret;
- }
- }
-
- dev_dbg(dsi->dev, "Start High Speed Clock with %s clock mode",
- is_clk_cont ? "continuous" : "non-continuous");
-
- return 0;
-}
-
-static int rzg2l_mipi_dsi_stop_hs_clock(struct rzg2l_mipi_dsi *dsi)
-{
- bool is_clk_cont;
- u32 status;
- int ret;
-
- is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS);
-
- /* Stop HS clock */
- rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR,
- is_clk_cont ? HSCLKSETR_HSCLKMODE_CONT :
- HSCLKSETR_HSCLKMODE_NON_CONT);
-
- if (is_clk_cont) {
- ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
- status & PLSR_CLHS2LP,
- 2000, 20000, false, dsi, PLSR);
- if (ret < 0) {
- dev_err(dsi->dev, "failed to stop HS clock\n");
- return ret;
- }
- }
-
- return 0;
-}
-
-static int rzg2l_mipi_dsi_start_video(struct rzg2l_mipi_dsi *dsi)
-{
- u32 vich1set0r;
- u32 status;
- int ret;
-
- /* Configuration for Blanking sequence and start video input*/
- vich1set0r = VICH1SET0R_HFPNOLP | VICH1SET0R_HBPNOLP |
- VICH1SET0R_HSANOLP | VICH1SET0R_VSTART;
- rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, vich1set0r);
-
- ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
- status & VICH1SR_VIRDY,
- 2000, 20000, false, dsi, VICH1SR);
- if (ret < 0)
- dev_err(dsi->dev, "Failed to start video signal input\n");
-
- return ret;
-}
-
-static int rzg2l_mipi_dsi_stop_video(struct rzg2l_mipi_dsi *dsi)
-{
- u32 status;
- int ret;
-
- rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, VICH1SET0R_VSTPAFT);
- ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
- (status & VICH1SR_STOP) && (!(status & VICH1SR_RUNNING)),
- 2000, 20000, false, dsi, VICH1SR);
- if (ret < 0)
- goto err;
-
- ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
- !(status & LINKSR_HSBUSY),
- 2000, 20000, false, dsi, LINKSR);
- if (ret < 0)
- goto err;
-
- return 0;
-
-err:
- dev_err(dsi->dev, "Failed to stop video signal input\n");
- return ret;
-}
-
-/* -----------------------------------------------------------------------------
- * Bridge
- */
-
-static int rzg2l_mipi_dsi_attach(struct drm_bridge *bridge,
- enum drm_bridge_attach_flags flags)
-{
- struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
-
- return drm_bridge_attach(bridge->encoder, dsi->next_bridge, bridge,
- flags);
-}
-
-static void rzg2l_mipi_dsi_atomic_enable(struct drm_bridge *bridge,
- struct drm_bridge_state *old_bridge_state)
-{
- struct drm_atomic_state *state = old_bridge_state->base.state;
- struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
- const struct drm_display_mode *mode;
- struct drm_connector *connector;
- struct drm_crtc *crtc;
- int ret;
-
- connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
- crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
- mode = &drm_atomic_get_new_crtc_state(state, crtc)->adjusted_mode;
-
- ret = rzg2l_mipi_dsi_startup(dsi, mode);
- if (ret < 0)
- return;
-
- rzg2l_mipi_dsi_set_display_timing(dsi, mode);
-
- ret = rzg2l_mipi_dsi_start_hs_clock(dsi);
- if (ret < 0)
- goto err_stop;
-
- ret = rzg2l_mipi_dsi_start_video(dsi);
- if (ret < 0)
- goto err_stop_clock;
-
- return;
-
-err_stop_clock:
- rzg2l_mipi_dsi_stop_hs_clock(dsi);
-err_stop:
- rzg2l_mipi_dsi_stop(dsi);
-}
-
-static void rzg2l_mipi_dsi_atomic_disable(struct drm_bridge *bridge,
- struct drm_bridge_state *old_bridge_state)
-{
- struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
-
- rzg2l_mipi_dsi_stop_video(dsi);
- rzg2l_mipi_dsi_stop_hs_clock(dsi);
- rzg2l_mipi_dsi_stop(dsi);
-}
-
-static enum drm_mode_status
-rzg2l_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge,
- const struct drm_display_info *info,
- const struct drm_display_mode *mode)
-{
- if (mode->clock > 148500)
- return MODE_CLOCK_HIGH;
-
- if (mode->clock < 5803)
- return MODE_CLOCK_LOW;
-
- return MODE_OK;
-}
-
-static const struct drm_bridge_funcs rzg2l_mipi_dsi_bridge_ops = {
- .attach = rzg2l_mipi_dsi_attach,
- .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
- .atomic_reset = drm_atomic_helper_bridge_reset,
- .atomic_enable = rzg2l_mipi_dsi_atomic_enable,
- .atomic_disable = rzg2l_mipi_dsi_atomic_disable,
- .mode_valid = rzg2l_mipi_dsi_bridge_mode_valid,
-};
-
-/* -----------------------------------------------------------------------------
- * Host setting
- */
-
-static int rzg2l_mipi_dsi_host_attach(struct mipi_dsi_host *host,
- struct mipi_dsi_device *device)
-{
- struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);
- int ret;
-
- if (device->lanes > dsi->num_data_lanes) {
- dev_err(dsi->dev,
- "Number of lines of device (%u) exceeds host (%u)\n",
- device->lanes, dsi->num_data_lanes);
- return -EINVAL;
- }
-
- switch (mipi_dsi_pixel_format_to_bpp(device->format)) {
- case 24:
- case 18:
- break;
- default:
- dev_err(dsi->dev, "Unsupported format 0x%04x\n", device->format);
- return -EINVAL;
- }
-
- dsi->lanes = device->lanes;
- dsi->format = device->format;
- dsi->mode_flags = device->mode_flags;
-
- dsi->next_bridge = devm_drm_of_get_bridge(dsi->dev, dsi->dev->of_node,
- 1, 0);
- if (IS_ERR(dsi->next_bridge)) {
- ret = PTR_ERR(dsi->next_bridge);
- dev_err(dsi->dev, "failed to get next bridge: %d\n", ret);
- return ret;
- }
-
- drm_bridge_add(&dsi->bridge);
-
- return 0;
-}
-
-static int rzg2l_mipi_dsi_host_detach(struct mipi_dsi_host *host,
- struct mipi_dsi_device *device)
-{
- struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);
-
- drm_bridge_remove(&dsi->bridge);
-
- return 0;
-}
-
-static const struct mipi_dsi_host_ops rzg2l_mipi_dsi_host_ops = {
- .attach = rzg2l_mipi_dsi_host_attach,
- .detach = rzg2l_mipi_dsi_host_detach,
-};
-
-/* -----------------------------------------------------------------------------
- * Power Management
- */
-
-static int __maybe_unused rzg2l_mipi_pm_runtime_suspend(struct device *dev)
-{
- struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev);
-
- reset_control_assert(dsi->prstc);
- reset_control_assert(dsi->arstc);
-
- return 0;
-}
-
-static int __maybe_unused rzg2l_mipi_pm_runtime_resume(struct device *dev)
-{
- struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev);
- int ret;
-
- ret = reset_control_deassert(dsi->arstc);
- if (ret < 0)
- return ret;
-
- ret = reset_control_deassert(dsi->prstc);
- if (ret < 0)
- reset_control_assert(dsi->arstc);
-
- return ret;
-}
-
-static const struct dev_pm_ops rzg2l_mipi_pm_ops = {
- SET_RUNTIME_PM_OPS(rzg2l_mipi_pm_runtime_suspend, rzg2l_mipi_pm_runtime_resume, NULL)
-};
-
-/* -----------------------------------------------------------------------------
- * Probe & Remove
- */
-
-static int rzg2l_mipi_dsi_probe(struct platform_device *pdev)
-{
- unsigned int num_data_lanes;
- struct rzg2l_mipi_dsi *dsi;
- u32 txsetr;
- int ret;
-
- dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL);
- if (!dsi)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, dsi);
- dsi->dev = &pdev->dev;
-
- ret = drm_of_get_data_lanes_count_ep(dsi->dev->of_node, 1, 0, 1, 4);
- if (ret < 0)
- return dev_err_probe(dsi->dev, ret,
- "missing or invalid data-lanes property\n");
-
- num_data_lanes = ret;
-
- dsi->mmio = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(dsi->mmio))
- return PTR_ERR(dsi->mmio);
-
- dsi->vclk = devm_clk_get(dsi->dev, "vclk");
- if (IS_ERR(dsi->vclk))
- return PTR_ERR(dsi->vclk);
-
- dsi->rstc = devm_reset_control_get_exclusive(dsi->dev, "rst");
- if (IS_ERR(dsi->rstc))
- return dev_err_probe(dsi->dev, PTR_ERR(dsi->rstc),
- "failed to get rst\n");
-
- dsi->arstc = devm_reset_control_get_exclusive(dsi->dev, "arst");
- if (IS_ERR(dsi->arstc))
- return dev_err_probe(&pdev->dev, PTR_ERR(dsi->arstc),
- "failed to get arst\n");
-
- dsi->prstc = devm_reset_control_get_exclusive(dsi->dev, "prst");
- if (IS_ERR(dsi->prstc))
- return dev_err_probe(dsi->dev, PTR_ERR(dsi->prstc),
- "failed to get prst\n");
-
- platform_set_drvdata(pdev, dsi);
-
- pm_runtime_enable(dsi->dev);
-
- ret = pm_runtime_resume_and_get(dsi->dev);
- if (ret < 0)
- goto err_pm_disable;
-
- /*
- * TXSETR register can be read only after DPHY init. But during probe
- * mode->clock and format are not available. So initialize DPHY with
- * timing parameters for 80Mbps.
- */
- ret = rzg2l_mipi_dsi_dphy_init(dsi, 80000);
- if (ret < 0)
- goto err_phy;
-
- txsetr = rzg2l_mipi_dsi_link_read(dsi, TXSETR);
- dsi->num_data_lanes = min(((txsetr >> 16) & 3) + 1, num_data_lanes);
- rzg2l_mipi_dsi_dphy_exit(dsi);
- pm_runtime_put(dsi->dev);
-
- /* Initialize the DRM bridge. */
- dsi->bridge.funcs = &rzg2l_mipi_dsi_bridge_ops;
- dsi->bridge.of_node = dsi->dev->of_node;
-
- /* Init host device */
- dsi->host.dev = dsi->dev;
- dsi->host.ops = &rzg2l_mipi_dsi_host_ops;
- ret = mipi_dsi_host_register(&dsi->host);
- if (ret < 0)
- goto err_pm_disable;
-
- return 0;
-
-err_phy:
- rzg2l_mipi_dsi_dphy_exit(dsi);
- pm_runtime_put(dsi->dev);
-err_pm_disable:
- pm_runtime_disable(dsi->dev);
- return ret;
-}
-
-static void rzg2l_mipi_dsi_remove(struct platform_device *pdev)
-{
- struct rzg2l_mipi_dsi *dsi = platform_get_drvdata(pdev);
-
- mipi_dsi_host_unregister(&dsi->host);
- pm_runtime_disable(&pdev->dev);
-}
-
-static const struct of_device_id rzg2l_mipi_dsi_of_table[] = {
- { .compatible = "renesas,rzg2l-mipi-dsi" },
- { /* sentinel */ }
-};
-
-MODULE_DEVICE_TABLE(of, rzg2l_mipi_dsi_of_table);
-
-static struct platform_driver rzg2l_mipi_dsi_platform_driver = {
- .probe = rzg2l_mipi_dsi_probe,
- .remove_new = rzg2l_mipi_dsi_remove,
- .driver = {
- .name = "rzg2l-mipi-dsi",
- .pm = &rzg2l_mipi_pm_ops,
- .of_match_table = rzg2l_mipi_dsi_of_table,
- },
-};
-
-module_platform_driver(rzg2l_mipi_dsi_platform_driver);
-
-MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
-MODULE_DESCRIPTION("Renesas RZ/G2L MIPI DSI Encoder Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/renesas/rcar-du/rzg2l_mipi_dsi_regs.h b/drivers/gpu/drm/renesas/rcar-du/rzg2l_mipi_dsi_regs.h
deleted file mode 100644
index 1dbc16ec64a4..000000000000
--- a/drivers/gpu/drm/renesas/rcar-du/rzg2l_mipi_dsi_regs.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * RZ/G2L MIPI DSI Interface Registers Definitions
- *
- * Copyright (C) 2022 Renesas Electronics Corporation
- */
-
-#ifndef __RZG2L_MIPI_DSI_REGS_H__
-#define __RZG2L_MIPI_DSI_REGS_H__
-
-#include <linux/bits.h>
-
-/* DPHY Registers */
-#define DSIDPHYCTRL0 0x00
-#define DSIDPHYCTRL0_CAL_EN_HSRX_OFS BIT(16)
-#define DSIDPHYCTRL0_CMN_MASTER_EN BIT(8)
-#define DSIDPHYCTRL0_RE_VDD_DETVCCQLV18 BIT(2)
-#define DSIDPHYCTRL0_EN_LDO1200 BIT(1)
-#define DSIDPHYCTRL0_EN_BGR BIT(0)
-
-#define DSIDPHYTIM0 0x04
-#define DSIDPHYTIM0_TCLK_MISS(x) ((x) << 24)
-#define DSIDPHYTIM0_T_INIT(x) ((x) << 0)
-
-#define DSIDPHYTIM1 0x08
-#define DSIDPHYTIM1_THS_PREPARE(x) ((x) << 24)
-#define DSIDPHYTIM1_TCLK_PREPARE(x) ((x) << 16)
-#define DSIDPHYTIM1_THS_SETTLE(x) ((x) << 8)
-#define DSIDPHYTIM1_TCLK_SETTLE(x) ((x) << 0)
-
-#define DSIDPHYTIM2 0x0c
-#define DSIDPHYTIM2_TCLK_TRAIL(x) ((x) << 24)
-#define DSIDPHYTIM2_TCLK_POST(x) ((x) << 16)
-#define DSIDPHYTIM2_TCLK_PRE(x) ((x) << 8)
-#define DSIDPHYTIM2_TCLK_ZERO(x) ((x) << 0)
-
-#define DSIDPHYTIM3 0x10
-#define DSIDPHYTIM3_TLPX(x) ((x) << 24)
-#define DSIDPHYTIM3_THS_EXIT(x) ((x) << 16)
-#define DSIDPHYTIM3_THS_TRAIL(x) ((x) << 8)
-#define DSIDPHYTIM3_THS_ZERO(x) ((x) << 0)
-
-/* --------------------------------------------------------*/
-/* Link Registers */
-#define LINK_REG_OFFSET 0x10000
-
-/* Link Status Register */
-#define LINKSR 0x10
-#define LINKSR_LPBUSY BIT(13)
-#define LINKSR_HSBUSY BIT(12)
-#define LINKSR_VICHRUN1 BIT(8)
-#define LINKSR_SQCHRUN1 BIT(4)
-#define LINKSR_SQCHRUN0 BIT(0)
-
-/* Tx Set Register */
-#define TXSETR 0x100
-#define TXSETR_NUMLANECAP (0x3 << 16)
-#define TXSETR_DLEN (1 << 9)
-#define TXSETR_CLEN (1 << 8)
-#define TXSETR_NUMLANEUSE(x) (((x) & 0x3) << 0)
-
-/* HS Clock Set Register */
-#define HSCLKSETR 0x104
-#define HSCLKSETR_HSCLKMODE_CONT (1 << 1)
-#define HSCLKSETR_HSCLKMODE_NON_CONT (0 << 1)
-#define HSCLKSETR_HSCLKRUN_HS (1 << 0)
-#define HSCLKSETR_HSCLKRUN_LP (0 << 0)
-
-/* Reset Control Register */
-#define RSTCR 0x110
-#define RSTCR_SWRST BIT(0)
-#define RSTCR_FCETXSTP BIT(16)
-
-/* Reset Status Register */
-#define RSTSR 0x114
-#define RSTSR_DL0DIR (1 << 15)
-#define RSTSR_DLSTPST (0xf << 8)
-#define RSTSR_SWRSTV1 (1 << 4)
-#define RSTSR_SWRSTIB (1 << 3)
-#define RSTSR_SWRSTAPB (1 << 2)
-#define RSTSR_SWRSTLP (1 << 1)
-#define RSTSR_SWRSTHS (1 << 0)
-
-/* Clock Lane Stop Time Set Register */
-#define CLSTPTSETR 0x314
-#define CLSTPTSETR_CLKKPT(x) ((x) << 24)
-#define CLSTPTSETR_CLKBFHT(x) ((x) << 16)
-#define CLSTPTSETR_CLKSTPT(x) ((x) << 2)
-
-/* LP Transition Time Set Register */
-#define LPTRNSTSETR 0x318
-#define LPTRNSTSETR_GOLPBKT(x) ((x) << 0)
-
-/* Physical Lane Status Register */
-#define PLSR 0x320
-#define PLSR_CLHS2LP BIT(27)
-#define PLSR_CLLP2HS BIT(26)
-
-/* Video-Input Channel 1 Set 0 Register */
-#define VICH1SET0R 0x400
-#define VICH1SET0R_VSEN BIT(12)
-#define VICH1SET0R_HFPNOLP BIT(10)
-#define VICH1SET0R_HBPNOLP BIT(9)
-#define VICH1SET0R_HSANOLP BIT(8)
-#define VICH1SET0R_VSTPAFT BIT(1)
-#define VICH1SET0R_VSTART BIT(0)
-
-/* Video-Input Channel 1 Set 1 Register */
-#define VICH1SET1R 0x404
-#define VICH1SET1R_DLY(x) (((x) & 0xfff) << 2)
-
-/* Video-Input Channel 1 Status Register */
-#define VICH1SR 0x410
-#define VICH1SR_VIRDY BIT(3)
-#define VICH1SR_RUNNING BIT(2)
-#define VICH1SR_STOP BIT(1)
-#define VICH1SR_START BIT(0)
-
-/* Video-Input Channel 1 Pixel Packet Set Register */
-#define VICH1PPSETR 0x420
-#define VICH1PPSETR_DT_RGB18 (0x1e << 16)
-#define VICH1PPSETR_DT_RGB18_LS (0x2e << 16)
-#define VICH1PPSETR_DT_RGB24 (0x3e << 16)
-#define VICH1PPSETR_TXESYNC_PULSE (1 << 15)
-#define VICH1PPSETR_VC(x) ((x) << 22)
-
-/* Video-Input Channel 1 Vertical Size Set Register */
-#define VICH1VSSETR 0x428
-#define VICH1VSSETR_VACTIVE(x) (((x) & 0x7fff) << 16)
-#define VICH1VSSETR_VSPOL_LOW (1 << 15)
-#define VICH1VSSETR_VSPOL_HIGH (0 << 15)
-#define VICH1VSSETR_VSA(x) (((x) & 0xfff) << 0)
-
-/* Video-Input Channel 1 Vertical Porch Set Register */
-#define VICH1VPSETR 0x42c
-#define VICH1VPSETR_VFP(x) (((x) & 0x1fff) << 16)
-#define VICH1VPSETR_VBP(x) (((x) & 0x1fff) << 0)
-
-/* Video-Input Channel 1 Horizontal Size Set Register */
-#define VICH1HSSETR 0x430
-#define VICH1HSSETR_HACTIVE(x) (((x) & 0x7fff) << 16)
-#define VICH1HSSETR_HSPOL_LOW (1 << 15)
-#define VICH1HSSETR_HSPOL_HIGH (0 << 15)
-#define VICH1HSSETR_HSA(x) (((x) & 0xfff) << 0)
-
-/* Video-Input Channel 1 Horizontal Porch Set Register */
-#define VICH1HPSETR 0x434
-#define VICH1HPSETR_HFP(x) (((x) & 0x1fff) << 16)
-#define VICH1HPSETR_HBP(x) (((x) & 0x1fff) << 0)
-
-#endif /* __RZG2L_MIPI_DSI_REGS_H__ */
diff --git a/drivers/gpu/drm/renesas/rz-du/Kconfig b/drivers/gpu/drm/renesas/rz-du/Kconfig
new file mode 100644
index 000000000000..8d97d6fd7ebe
--- /dev/null
+++ b/drivers/gpu/drm/renesas/rz-du/Kconfig
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
+config DRM_RZG2L_MIPI_DSI
+ tristate "RZ/G2L MIPI DSI Encoder Support"
+ depends on DRM && DRM_BRIDGE && OF
+ depends on ARCH_RENESAS || COMPILE_TEST
+ select DRM_MIPI_DSI
+ help
+ Enable support for the RZ/G2L Display Unit embedded MIPI DSI encoders.
diff --git a/drivers/gpu/drm/renesas/rz-du/Makefile b/drivers/gpu/drm/renesas/rz-du/Makefile
new file mode 100644
index 000000000000..5b2b2ddf097c
--- /dev/null
+++ b/drivers/gpu/drm/renesas/rz-du/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_DRM_RZG2L_MIPI_DSI) += rzg2l_mipi_dsi.o
diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
new file mode 100644
index 000000000000..a9216a99b2be
--- /dev/null
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
@@ -0,0 +1,816 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RZ/G2L MIPI DSI Encoder Driver
+ *
+ * Copyright (C) 2022 Renesas Electronics Corporation
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_probe_helper.h>
+
+#include "rzg2l_mipi_dsi_regs.h"
+
+struct rzg2l_mipi_dsi {
+ struct device *dev;
+ void __iomem *mmio;
+
+ struct reset_control *rstc;
+ struct reset_control *arstc;
+ struct reset_control *prstc;
+
+ struct mipi_dsi_host host;
+ struct drm_bridge bridge;
+ struct drm_bridge *next_bridge;
+
+ struct clk *vclk;
+
+ enum mipi_dsi_pixel_format format;
+ unsigned int num_data_lanes;
+ unsigned int lanes;
+ unsigned long mode_flags;
+};
+
+static inline struct rzg2l_mipi_dsi *
+bridge_to_rzg2l_mipi_dsi(struct drm_bridge *bridge)
+{
+ return container_of(bridge, struct rzg2l_mipi_dsi, bridge);
+}
+
+static inline struct rzg2l_mipi_dsi *
+host_to_rzg2l_mipi_dsi(struct mipi_dsi_host *host)
+{
+ return container_of(host, struct rzg2l_mipi_dsi, host);
+}
+
+struct rzg2l_mipi_dsi_timings {
+ unsigned long hsfreq_max;
+ u32 t_init;
+ u32 tclk_prepare;
+ u32 ths_prepare;
+ u32 tclk_zero;
+ u32 tclk_pre;
+ u32 tclk_post;
+ u32 tclk_trail;
+ u32 ths_zero;
+ u32 ths_trail;
+ u32 ths_exit;
+ u32 tlpx;
+};
+
+static const struct rzg2l_mipi_dsi_timings rzg2l_mipi_dsi_global_timings[] = {
+ {
+ .hsfreq_max = 80000,
+ .t_init = 79801,
+ .tclk_prepare = 8,
+ .ths_prepare = 13,
+ .tclk_zero = 33,
+ .tclk_pre = 24,
+ .tclk_post = 94,
+ .tclk_trail = 10,
+ .ths_zero = 23,
+ .ths_trail = 17,
+ .ths_exit = 13,
+ .tlpx = 6,
+ },
+ {
+ .hsfreq_max = 125000,
+ .t_init = 79801,
+ .tclk_prepare = 8,
+ .ths_prepare = 12,
+ .tclk_zero = 33,
+ .tclk_pre = 15,
+ .tclk_post = 94,
+ .tclk_trail = 10,
+ .ths_zero = 23,
+ .ths_trail = 17,
+ .ths_exit = 13,
+ .tlpx = 6,
+ },
+ {
+ .hsfreq_max = 250000,
+ .t_init = 79801,
+ .tclk_prepare = 8,
+ .ths_prepare = 12,
+ .tclk_zero = 33,
+ .tclk_pre = 13,
+ .tclk_post = 94,
+ .tclk_trail = 10,
+ .ths_zero = 23,
+ .ths_trail = 16,
+ .ths_exit = 13,
+ .tlpx = 6,
+ },
+ {
+ .hsfreq_max = 360000,
+ .t_init = 79801,
+ .tclk_prepare = 8,
+ .ths_prepare = 10,
+ .tclk_zero = 33,
+ .tclk_pre = 4,
+ .tclk_post = 35,
+ .tclk_trail = 7,
+ .ths_zero = 16,
+ .ths_trail = 9,
+ .ths_exit = 13,
+ .tlpx = 6,
+ },
+ {
+ .hsfreq_max = 720000,
+ .t_init = 79801,
+ .tclk_prepare = 8,
+ .ths_prepare = 9,
+ .tclk_zero = 33,
+ .tclk_pre = 4,
+ .tclk_post = 35,
+ .tclk_trail = 7,
+ .ths_zero = 16,
+ .ths_trail = 9,
+ .ths_exit = 13,
+ .tlpx = 6,
+ },
+ {
+ .hsfreq_max = 1500000,
+ .t_init = 79801,
+ .tclk_prepare = 8,
+ .ths_prepare = 9,
+ .tclk_zero = 33,
+ .tclk_pre = 4,
+ .tclk_post = 35,
+ .tclk_trail = 7,
+ .ths_zero = 16,
+ .ths_trail = 9,
+ .ths_exit = 13,
+ .tlpx = 6,
+ },
+};
+
+static void rzg2l_mipi_dsi_phy_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data)
+{
+ iowrite32(data, dsi->mmio + reg);
+}
+
+static void rzg2l_mipi_dsi_link_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data)
+{
+ iowrite32(data, dsi->mmio + LINK_REG_OFFSET + reg);
+}
+
+static u32 rzg2l_mipi_dsi_phy_read(struct rzg2l_mipi_dsi *dsi, u32 reg)
+{
+ return ioread32(dsi->mmio + reg);
+}
+
+static u32 rzg2l_mipi_dsi_link_read(struct rzg2l_mipi_dsi *dsi, u32 reg)
+{
+ return ioread32(dsi->mmio + LINK_REG_OFFSET + reg);
+}
+
+/* -----------------------------------------------------------------------------
+ * Hardware Setup
+ */
+
+static int rzg2l_mipi_dsi_dphy_init(struct rzg2l_mipi_dsi *dsi,
+ unsigned long hsfreq)
+{
+ const struct rzg2l_mipi_dsi_timings *dphy_timings;
+ unsigned int i;
+ u32 dphyctrl0;
+ u32 dphytim0;
+ u32 dphytim1;
+ u32 dphytim2;
+ u32 dphytim3;
+ int ret;
+
+ /* All DSI global operation timings are set with recommended setting */
+ for (i = 0; i < ARRAY_SIZE(rzg2l_mipi_dsi_global_timings); ++i) {
+ dphy_timings = &rzg2l_mipi_dsi_global_timings[i];
+ if (hsfreq <= dphy_timings->hsfreq_max)
+ break;
+ }
+
+ /* Initializing DPHY before accessing LINK */
+ dphyctrl0 = DSIDPHYCTRL0_CAL_EN_HSRX_OFS | DSIDPHYCTRL0_CMN_MASTER_EN |
+ DSIDPHYCTRL0_RE_VDD_DETVCCQLV18 | DSIDPHYCTRL0_EN_BGR;
+
+ rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);
+ usleep_range(20, 30);
+
+ dphyctrl0 |= DSIDPHYCTRL0_EN_LDO1200;
+ rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);
+ usleep_range(10, 20);
+
+ dphytim0 = DSIDPHYTIM0_TCLK_MISS(0) |
+ DSIDPHYTIM0_T_INIT(dphy_timings->t_init);
+ dphytim1 = DSIDPHYTIM1_THS_PREPARE(dphy_timings->ths_prepare) |
+ DSIDPHYTIM1_TCLK_PREPARE(dphy_timings->tclk_prepare) |
+ DSIDPHYTIM1_THS_SETTLE(0) |
+ DSIDPHYTIM1_TCLK_SETTLE(0);
+ dphytim2 = DSIDPHYTIM2_TCLK_TRAIL(dphy_timings->tclk_trail) |
+ DSIDPHYTIM2_TCLK_POST(dphy_timings->tclk_post) |
+ DSIDPHYTIM2_TCLK_PRE(dphy_timings->tclk_pre) |
+ DSIDPHYTIM2_TCLK_ZERO(dphy_timings->tclk_zero);
+ dphytim3 = DSIDPHYTIM3_TLPX(dphy_timings->tlpx) |
+ DSIDPHYTIM3_THS_EXIT(dphy_timings->ths_exit) |
+ DSIDPHYTIM3_THS_TRAIL(dphy_timings->ths_trail) |
+ DSIDPHYTIM3_THS_ZERO(dphy_timings->ths_zero);
+
+ rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM0, dphytim0);
+ rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM1, dphytim1);
+ rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM2, dphytim2);
+ rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM3, dphytim3);
+
+ ret = reset_control_deassert(dsi->rstc);
+ if (ret < 0)
+ return ret;
+
+ fsleep(1000);
+
+ return 0;
+}
+
+static void rzg2l_mipi_dsi_dphy_exit(struct rzg2l_mipi_dsi *dsi)
+{
+ u32 dphyctrl0;
+
+ dphyctrl0 = rzg2l_mipi_dsi_phy_read(dsi, DSIDPHYCTRL0);
+
+ dphyctrl0 &= ~(DSIDPHYCTRL0_EN_LDO1200 | DSIDPHYCTRL0_EN_BGR);
+ rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);
+
+ reset_control_assert(dsi->rstc);
+}
+
+static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
+ const struct drm_display_mode *mode)
+{
+ unsigned long hsfreq;
+ unsigned int bpp;
+ u32 txsetr;
+ u32 clstptsetr;
+ u32 lptrnstsetr;
+ u32 clkkpt;
+ u32 clkbfht;
+ u32 clkstpt;
+ u32 golpbkt;
+ int ret;
+
+ /*
+ * Relationship between hsclk and vclk must follow
+ * vclk * bpp = hsclk * 8 * lanes
+ * where vclk: video clock (Hz)
+ * bpp: video pixel bit depth
+ * hsclk: DSI HS Byte clock frequency (Hz)
+ * lanes: number of data lanes
+ *
+ * hsclk(bit) = hsclk(byte) * 8
+ */
+ bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
+ hsfreq = (mode->clock * bpp * 8) / (8 * dsi->lanes);
+
+ ret = pm_runtime_resume_and_get(dsi->dev);
+ if (ret < 0)
+ return ret;
+
+ clk_set_rate(dsi->vclk, mode->clock * 1000);
+
+ ret = rzg2l_mipi_dsi_dphy_init(dsi, hsfreq);
+ if (ret < 0)
+ goto err_phy;
+
+ /* Enable Data lanes and Clock lanes */
+ txsetr = TXSETR_DLEN | TXSETR_NUMLANEUSE(dsi->lanes - 1) | TXSETR_CLEN;
+ rzg2l_mipi_dsi_link_write(dsi, TXSETR, txsetr);
+
+ /*
+ * Global timings characteristic depends on high speed Clock Frequency
+ * Currently MIPI DSI-IF just supports maximum FHD@60 with:
+ * - videoclock = 148.5 (MHz)
+ * - bpp: maximum 24bpp
+ * - data lanes: maximum 4 lanes
+ * Therefore maximum hsclk will be 891 Mbps.
+ */
+ if (hsfreq > 445500) {
+ clkkpt = 12;
+ clkbfht = 15;
+ clkstpt = 48;
+ golpbkt = 75;
+ } else if (hsfreq > 250000) {
+ clkkpt = 7;
+ clkbfht = 8;
+ clkstpt = 27;
+ golpbkt = 40;
+ } else {
+ clkkpt = 8;
+ clkbfht = 6;
+ clkstpt = 24;
+ golpbkt = 29;
+ }
+
+ clstptsetr = CLSTPTSETR_CLKKPT(clkkpt) | CLSTPTSETR_CLKBFHT(clkbfht) |
+ CLSTPTSETR_CLKSTPT(clkstpt);
+ rzg2l_mipi_dsi_link_write(dsi, CLSTPTSETR, clstptsetr);
+
+ lptrnstsetr = LPTRNSTSETR_GOLPBKT(golpbkt);
+ rzg2l_mipi_dsi_link_write(dsi, LPTRNSTSETR, lptrnstsetr);
+
+ return 0;
+
+err_phy:
+ rzg2l_mipi_dsi_dphy_exit(dsi);
+ pm_runtime_put(dsi->dev);
+
+ return ret;
+}
+
+static void rzg2l_mipi_dsi_stop(struct rzg2l_mipi_dsi *dsi)
+{
+ rzg2l_mipi_dsi_dphy_exit(dsi);
+ pm_runtime_put(dsi->dev);
+}
+
+static void rzg2l_mipi_dsi_set_display_timing(struct rzg2l_mipi_dsi *dsi,
+ const struct drm_display_mode *mode)
+{
+ u32 vich1ppsetr;
+ u32 vich1vssetr;
+ u32 vich1vpsetr;
+ u32 vich1hssetr;
+ u32 vich1hpsetr;
+ int dsi_format;
+ u32 delay[2];
+ u8 index;
+
+ /* Configuration for Pixel Packet */
+ dsi_format = mipi_dsi_pixel_format_to_bpp(dsi->format);
+ switch (dsi_format) {
+ case 24:
+ vich1ppsetr = VICH1PPSETR_DT_RGB24;
+ break;
+ case 18:
+ vich1ppsetr = VICH1PPSETR_DT_RGB18;
+ break;
+ }
+
+ if ((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) &&
+ !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST))
+ vich1ppsetr |= VICH1PPSETR_TXESYNC_PULSE;
+
+ rzg2l_mipi_dsi_link_write(dsi, VICH1PPSETR, vich1ppsetr);
+
+ /* Configuration for Video Parameters */
+ vich1vssetr = VICH1VSSETR_VACTIVE(mode->vdisplay) |
+ VICH1VSSETR_VSA(mode->vsync_end - mode->vsync_start);
+ vich1vssetr |= (mode->flags & DRM_MODE_FLAG_PVSYNC) ?
+ VICH1VSSETR_VSPOL_HIGH : VICH1VSSETR_VSPOL_LOW;
+
+ vich1vpsetr = VICH1VPSETR_VFP(mode->vsync_start - mode->vdisplay) |
+ VICH1VPSETR_VBP(mode->vtotal - mode->vsync_end);
+
+ vich1hssetr = VICH1HSSETR_HACTIVE(mode->hdisplay) |
+ VICH1HSSETR_HSA(mode->hsync_end - mode->hsync_start);
+ vich1hssetr |= (mode->flags & DRM_MODE_FLAG_PHSYNC) ?
+ VICH1HSSETR_HSPOL_HIGH : VICH1HSSETR_HSPOL_LOW;
+
+ vich1hpsetr = VICH1HPSETR_HFP(mode->hsync_start - mode->hdisplay) |
+ VICH1HPSETR_HBP(mode->htotal - mode->hsync_end);
+
+ rzg2l_mipi_dsi_link_write(dsi, VICH1VSSETR, vich1vssetr);
+ rzg2l_mipi_dsi_link_write(dsi, VICH1VPSETR, vich1vpsetr);
+ rzg2l_mipi_dsi_link_write(dsi, VICH1HSSETR, vich1hssetr);
+ rzg2l_mipi_dsi_link_write(dsi, VICH1HPSETR, vich1hpsetr);
+
+ /*
+ * Configuration for Delay Value
+ * Delay value based on 2 ranges of video clock.
+ * 74.25MHz is videoclock of HD@60p or FHD@30p
+ */
+ if (mode->clock > 74250) {
+ delay[0] = 231;
+ delay[1] = 216;
+ } else {
+ delay[0] = 220;
+ delay[1] = 212;
+ }
+
+ if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
+ index = 0;
+ else
+ index = 1;
+
+ rzg2l_mipi_dsi_link_write(dsi, VICH1SET1R,
+ VICH1SET1R_DLY(delay[index]));
+}
+
+static int rzg2l_mipi_dsi_start_hs_clock(struct rzg2l_mipi_dsi *dsi)
+{
+ bool is_clk_cont;
+ u32 hsclksetr;
+ u32 status;
+ int ret;
+
+ is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS);
+
+ /* Start HS clock */
+ hsclksetr = HSCLKSETR_HSCLKRUN_HS | (is_clk_cont ?
+ HSCLKSETR_HSCLKMODE_CONT :
+ HSCLKSETR_HSCLKMODE_NON_CONT);
+ rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR, hsclksetr);
+
+ if (is_clk_cont) {
+ ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
+ status & PLSR_CLLP2HS,
+ 2000, 20000, false, dsi, PLSR);
+ if (ret < 0) {
+ dev_err(dsi->dev, "failed to start HS clock\n");
+ return ret;
+ }
+ }
+
+ dev_dbg(dsi->dev, "Start High Speed Clock with %s clock mode",
+ is_clk_cont ? "continuous" : "non-continuous");
+
+ return 0;
+}
+
+static int rzg2l_mipi_dsi_stop_hs_clock(struct rzg2l_mipi_dsi *dsi)
+{
+ bool is_clk_cont;
+ u32 status;
+ int ret;
+
+ is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS);
+
+ /* Stop HS clock */
+ rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR,
+ is_clk_cont ? HSCLKSETR_HSCLKMODE_CONT :
+ HSCLKSETR_HSCLKMODE_NON_CONT);
+
+ if (is_clk_cont) {
+ ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
+ status & PLSR_CLHS2LP,
+ 2000, 20000, false, dsi, PLSR);
+ if (ret < 0) {
+ dev_err(dsi->dev, "failed to stop HS clock\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int rzg2l_mipi_dsi_start_video(struct rzg2l_mipi_dsi *dsi)
+{
+ u32 vich1set0r;
+ u32 status;
+ int ret;
+
+ /* Configuration for Blanking sequence and start video input*/
+ vich1set0r = VICH1SET0R_HFPNOLP | VICH1SET0R_HBPNOLP |
+ VICH1SET0R_HSANOLP | VICH1SET0R_VSTART;
+ rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, vich1set0r);
+
+ ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
+ status & VICH1SR_VIRDY,
+ 2000, 20000, false, dsi, VICH1SR);
+ if (ret < 0)
+ dev_err(dsi->dev, "Failed to start video signal input\n");
+
+ return ret;
+}
+
+static int rzg2l_mipi_dsi_stop_video(struct rzg2l_mipi_dsi *dsi)
+{
+ u32 status;
+ int ret;
+
+ rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, VICH1SET0R_VSTPAFT);
+ ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
+ (status & VICH1SR_STOP) && (!(status & VICH1SR_RUNNING)),
+ 2000, 20000, false, dsi, VICH1SR);
+ if (ret < 0)
+ goto err;
+
+ ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
+ !(status & LINKSR_HSBUSY),
+ 2000, 20000, false, dsi, LINKSR);
+ if (ret < 0)
+ goto err;
+
+ return 0;
+
+err:
+ dev_err(dsi->dev, "Failed to stop video signal input\n");
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Bridge
+ */
+
+static int rzg2l_mipi_dsi_attach(struct drm_bridge *bridge,
+ enum drm_bridge_attach_flags flags)
+{
+ struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
+
+ return drm_bridge_attach(bridge->encoder, dsi->next_bridge, bridge,
+ flags);
+}
+
+static void rzg2l_mipi_dsi_atomic_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
+{
+ struct drm_atomic_state *state = old_bridge_state->base.state;
+ struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
+ const struct drm_display_mode *mode;
+ struct drm_connector *connector;
+ struct drm_crtc *crtc;
+ int ret;
+
+ connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
+ crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
+ mode = &drm_atomic_get_new_crtc_state(state, crtc)->adjusted_mode;
+
+ ret = rzg2l_mipi_dsi_startup(dsi, mode);
+ if (ret < 0)
+ return;
+
+ rzg2l_mipi_dsi_set_display_timing(dsi, mode);
+
+ ret = rzg2l_mipi_dsi_start_hs_clock(dsi);
+ if (ret < 0)
+ goto err_stop;
+
+ ret = rzg2l_mipi_dsi_start_video(dsi);
+ if (ret < 0)
+ goto err_stop_clock;
+
+ return;
+
+err_stop_clock:
+ rzg2l_mipi_dsi_stop_hs_clock(dsi);
+err_stop:
+ rzg2l_mipi_dsi_stop(dsi);
+}
+
+static void rzg2l_mipi_dsi_atomic_disable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
+{
+ struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
+
+ rzg2l_mipi_dsi_stop_video(dsi);
+ rzg2l_mipi_dsi_stop_hs_clock(dsi);
+ rzg2l_mipi_dsi_stop(dsi);
+}
+
+static enum drm_mode_status
+rzg2l_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge,
+ const struct drm_display_info *info,
+ const struct drm_display_mode *mode)
+{
+ if (mode->clock > 148500)
+ return MODE_CLOCK_HIGH;
+
+ if (mode->clock < 5803)
+ return MODE_CLOCK_LOW;
+
+ return MODE_OK;
+}
+
+static const struct drm_bridge_funcs rzg2l_mipi_dsi_bridge_ops = {
+ .attach = rzg2l_mipi_dsi_attach,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_reset = drm_atomic_helper_bridge_reset,
+ .atomic_enable = rzg2l_mipi_dsi_atomic_enable,
+ .atomic_disable = rzg2l_mipi_dsi_atomic_disable,
+ .mode_valid = rzg2l_mipi_dsi_bridge_mode_valid,
+};
+
+/* -----------------------------------------------------------------------------
+ * Host setting
+ */
+
+static int rzg2l_mipi_dsi_host_attach(struct mipi_dsi_host *host,
+ struct mipi_dsi_device *device)
+{
+ struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);
+ int ret;
+
+ if (device->lanes > dsi->num_data_lanes) {
+ dev_err(dsi->dev,
+ "Number of lines of device (%u) exceeds host (%u)\n",
+ device->lanes, dsi->num_data_lanes);
+ return -EINVAL;
+ }
+
+ switch (mipi_dsi_pixel_format_to_bpp(device->format)) {
+ case 24:
+ case 18:
+ break;
+ default:
+ dev_err(dsi->dev, "Unsupported format 0x%04x\n", device->format);
+ return -EINVAL;
+ }
+
+ dsi->lanes = device->lanes;
+ dsi->format = device->format;
+ dsi->mode_flags = device->mode_flags;
+
+ dsi->next_bridge = devm_drm_of_get_bridge(dsi->dev, dsi->dev->of_node,
+ 1, 0);
+ if (IS_ERR(dsi->next_bridge)) {
+ ret = PTR_ERR(dsi->next_bridge);
+ dev_err(dsi->dev, "failed to get next bridge: %d\n", ret);
+ return ret;
+ }
+
+ drm_bridge_add(&dsi->bridge);
+
+ return 0;
+}
+
+static int rzg2l_mipi_dsi_host_detach(struct mipi_dsi_host *host,
+ struct mipi_dsi_device *device)
+{
+ struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);
+
+ drm_bridge_remove(&dsi->bridge);
+
+ return 0;
+}
+
+static const struct mipi_dsi_host_ops rzg2l_mipi_dsi_host_ops = {
+ .attach = rzg2l_mipi_dsi_host_attach,
+ .detach = rzg2l_mipi_dsi_host_detach,
+};
+
+/* -----------------------------------------------------------------------------
+ * Power Management
+ */
+
+static int __maybe_unused rzg2l_mipi_pm_runtime_suspend(struct device *dev)
+{
+ struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev);
+
+ reset_control_assert(dsi->prstc);
+ reset_control_assert(dsi->arstc);
+
+ return 0;
+}
+
+static int __maybe_unused rzg2l_mipi_pm_runtime_resume(struct device *dev)
+{
+ struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev);
+ int ret;
+
+ ret = reset_control_deassert(dsi->arstc);
+ if (ret < 0)
+ return ret;
+
+ ret = reset_control_deassert(dsi->prstc);
+ if (ret < 0)
+ reset_control_assert(dsi->arstc);
+
+ return ret;
+}
+
+static const struct dev_pm_ops rzg2l_mipi_pm_ops = {
+ SET_RUNTIME_PM_OPS(rzg2l_mipi_pm_runtime_suspend, rzg2l_mipi_pm_runtime_resume, NULL)
+};
+
+/* -----------------------------------------------------------------------------
+ * Probe & Remove
+ */
+
+static int rzg2l_mipi_dsi_probe(struct platform_device *pdev)
+{
+ unsigned int num_data_lanes;
+ struct rzg2l_mipi_dsi *dsi;
+ u32 txsetr;
+ int ret;
+
+ dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL);
+ if (!dsi)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, dsi);
+ dsi->dev = &pdev->dev;
+
+ ret = drm_of_get_data_lanes_count_ep(dsi->dev->of_node, 1, 0, 1, 4);
+ if (ret < 0)
+ return dev_err_probe(dsi->dev, ret,
+ "missing or invalid data-lanes property\n");
+
+ num_data_lanes = ret;
+
+ dsi->mmio = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(dsi->mmio))
+ return PTR_ERR(dsi->mmio);
+
+ dsi->vclk = devm_clk_get(dsi->dev, "vclk");
+ if (IS_ERR(dsi->vclk))
+ return PTR_ERR(dsi->vclk);
+
+ dsi->rstc = devm_reset_control_get_exclusive(dsi->dev, "rst");
+ if (IS_ERR(dsi->rstc))
+ return dev_err_probe(dsi->dev, PTR_ERR(dsi->rstc),
+ "failed to get rst\n");
+
+ dsi->arstc = devm_reset_control_get_exclusive(dsi->dev, "arst");
+ if (IS_ERR(dsi->arstc))
+ return dev_err_probe(&pdev->dev, PTR_ERR(dsi->arstc),
+ "failed to get arst\n");
+
+ dsi->prstc = devm_reset_control_get_exclusive(dsi->dev, "prst");
+ if (IS_ERR(dsi->prstc))
+ return dev_err_probe(dsi->dev, PTR_ERR(dsi->prstc),
+ "failed to get prst\n");
+
+ platform_set_drvdata(pdev, dsi);
+
+ pm_runtime_enable(dsi->dev);
+
+ ret = pm_runtime_resume_and_get(dsi->dev);
+ if (ret < 0)
+ goto err_pm_disable;
+
+ /*
+ * TXSETR register can be read only after DPHY init. But during probe
+ * mode->clock and format are not available. So initialize DPHY with
+ * timing parameters for 80Mbps.
+ */
+ ret = rzg2l_mipi_dsi_dphy_init(dsi, 80000);
+ if (ret < 0)
+ goto err_phy;
+
+ txsetr = rzg2l_mipi_dsi_link_read(dsi, TXSETR);
+ dsi->num_data_lanes = min(((txsetr >> 16) & 3) + 1, num_data_lanes);
+ rzg2l_mipi_dsi_dphy_exit(dsi);
+ pm_runtime_put(dsi->dev);
+
+ /* Initialize the DRM bridge. */
+ dsi->bridge.funcs = &rzg2l_mipi_dsi_bridge_ops;
+ dsi->bridge.of_node = dsi->dev->of_node;
+
+ /* Init host device */
+ dsi->host.dev = dsi->dev;
+ dsi->host.ops = &rzg2l_mipi_dsi_host_ops;
+ ret = mipi_dsi_host_register(&dsi->host);
+ if (ret < 0)
+ goto err_pm_disable;
+
+ return 0;
+
+err_phy:
+ rzg2l_mipi_dsi_dphy_exit(dsi);
+ pm_runtime_put(dsi->dev);
+err_pm_disable:
+ pm_runtime_disable(dsi->dev);
+ return ret;
+}
+
+static void rzg2l_mipi_dsi_remove(struct platform_device *pdev)
+{
+ struct rzg2l_mipi_dsi *dsi = platform_get_drvdata(pdev);
+
+ mipi_dsi_host_unregister(&dsi->host);
+ pm_runtime_disable(&pdev->dev);
+}
+
+static const struct of_device_id rzg2l_mipi_dsi_of_table[] = {
+ { .compatible = "renesas,rzg2l-mipi-dsi" },
+ { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, rzg2l_mipi_dsi_of_table);
+
+static struct platform_driver rzg2l_mipi_dsi_platform_driver = {
+ .probe = rzg2l_mipi_dsi_probe,
+ .remove_new = rzg2l_mipi_dsi_remove,
+ .driver = {
+ .name = "rzg2l-mipi-dsi",
+ .pm = &rzg2l_mipi_pm_ops,
+ .of_match_table = rzg2l_mipi_dsi_of_table,
+ },
+};
+
+module_platform_driver(rzg2l_mipi_dsi_platform_driver);
+
+MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
+MODULE_DESCRIPTION("Renesas RZ/G2L MIPI DSI Encoder Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h
new file mode 100644
index 000000000000..1dbc16ec64a4
--- /dev/null
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * RZ/G2L MIPI DSI Interface Registers Definitions
+ *
+ * Copyright (C) 2022 Renesas Electronics Corporation
+ */
+
+#ifndef __RZG2L_MIPI_DSI_REGS_H__
+#define __RZG2L_MIPI_DSI_REGS_H__
+
+#include <linux/bits.h>
+
+/* DPHY Registers */
+#define DSIDPHYCTRL0 0x00
+#define DSIDPHYCTRL0_CAL_EN_HSRX_OFS BIT(16)
+#define DSIDPHYCTRL0_CMN_MASTER_EN BIT(8)
+#define DSIDPHYCTRL0_RE_VDD_DETVCCQLV18 BIT(2)
+#define DSIDPHYCTRL0_EN_LDO1200 BIT(1)
+#define DSIDPHYCTRL0_EN_BGR BIT(0)
+
+#define DSIDPHYTIM0 0x04
+#define DSIDPHYTIM0_TCLK_MISS(x) ((x) << 24)
+#define DSIDPHYTIM0_T_INIT(x) ((x) << 0)
+
+#define DSIDPHYTIM1 0x08
+#define DSIDPHYTIM1_THS_PREPARE(x) ((x) << 24)
+#define DSIDPHYTIM1_TCLK_PREPARE(x) ((x) << 16)
+#define DSIDPHYTIM1_THS_SETTLE(x) ((x) << 8)
+#define DSIDPHYTIM1_TCLK_SETTLE(x) ((x) << 0)
+
+#define DSIDPHYTIM2 0x0c
+#define DSIDPHYTIM2_TCLK_TRAIL(x) ((x) << 24)
+#define DSIDPHYTIM2_TCLK_POST(x) ((x) << 16)
+#define DSIDPHYTIM2_TCLK_PRE(x) ((x) << 8)
+#define DSIDPHYTIM2_TCLK_ZERO(x) ((x) << 0)
+
+#define DSIDPHYTIM3 0x10
+#define DSIDPHYTIM3_TLPX(x) ((x) << 24)
+#define DSIDPHYTIM3_THS_EXIT(x) ((x) << 16)
+#define DSIDPHYTIM3_THS_TRAIL(x) ((x) << 8)
+#define DSIDPHYTIM3_THS_ZERO(x) ((x) << 0)
+
+/* --------------------------------------------------------*/
+/* Link Registers */
+#define LINK_REG_OFFSET 0x10000
+
+/* Link Status Register */
+#define LINKSR 0x10
+#define LINKSR_LPBUSY BIT(13)
+#define LINKSR_HSBUSY BIT(12)
+#define LINKSR_VICHRUN1 BIT(8)
+#define LINKSR_SQCHRUN1 BIT(4)
+#define LINKSR_SQCHRUN0 BIT(0)
+
+/* Tx Set Register */
+#define TXSETR 0x100
+#define TXSETR_NUMLANECAP (0x3 << 16)
+#define TXSETR_DLEN (1 << 9)
+#define TXSETR_CLEN (1 << 8)
+#define TXSETR_NUMLANEUSE(x) (((x) & 0x3) << 0)
+
+/* HS Clock Set Register */
+#define HSCLKSETR 0x104
+#define HSCLKSETR_HSCLKMODE_CONT (1 << 1)
+#define HSCLKSETR_HSCLKMODE_NON_CONT (0 << 1)
+#define HSCLKSETR_HSCLKRUN_HS (1 << 0)
+#define HSCLKSETR_HSCLKRUN_LP (0 << 0)
+
+/* Reset Control Register */
+#define RSTCR 0x110
+#define RSTCR_SWRST BIT(0)
+#define RSTCR_FCETXSTP BIT(16)
+
+/* Reset Status Register */
+#define RSTSR 0x114
+#define RSTSR_DL0DIR (1 << 15)
+#define RSTSR_DLSTPST (0xf << 8)
+#define RSTSR_SWRSTV1 (1 << 4)
+#define RSTSR_SWRSTIB (1 << 3)
+#define RSTSR_SWRSTAPB (1 << 2)
+#define RSTSR_SWRSTLP (1 << 1)
+#define RSTSR_SWRSTHS (1 << 0)
+
+/* Clock Lane Stop Time Set Register */
+#define CLSTPTSETR 0x314
+#define CLSTPTSETR_CLKKPT(x) ((x) << 24)
+#define CLSTPTSETR_CLKBFHT(x) ((x) << 16)
+#define CLSTPTSETR_CLKSTPT(x) ((x) << 2)
+
+/* LP Transition Time Set Register */
+#define LPTRNSTSETR 0x318
+#define LPTRNSTSETR_GOLPBKT(x) ((x) << 0)
+
+/* Physical Lane Status Register */
+#define PLSR 0x320
+#define PLSR_CLHS2LP BIT(27)
+#define PLSR_CLLP2HS BIT(26)
+
+/* Video-Input Channel 1 Set 0 Register */
+#define VICH1SET0R 0x400
+#define VICH1SET0R_VSEN BIT(12)
+#define VICH1SET0R_HFPNOLP BIT(10)
+#define VICH1SET0R_HBPNOLP BIT(9)
+#define VICH1SET0R_HSANOLP BIT(8)
+#define VICH1SET0R_VSTPAFT BIT(1)
+#define VICH1SET0R_VSTART BIT(0)
+
+/* Video-Input Channel 1 Set 1 Register */
+#define VICH1SET1R 0x404
+#define VICH1SET1R_DLY(x) (((x) & 0xfff) << 2)
+
+/* Video-Input Channel 1 Status Register */
+#define VICH1SR 0x410
+#define VICH1SR_VIRDY BIT(3)
+#define VICH1SR_RUNNING BIT(2)
+#define VICH1SR_STOP BIT(1)
+#define VICH1SR_START BIT(0)
+
+/* Video-Input Channel 1 Pixel Packet Set Register */
+#define VICH1PPSETR 0x420
+#define VICH1PPSETR_DT_RGB18 (0x1e << 16)
+#define VICH1PPSETR_DT_RGB18_LS (0x2e << 16)
+#define VICH1PPSETR_DT_RGB24 (0x3e << 16)
+#define VICH1PPSETR_TXESYNC_PULSE (1 << 15)
+#define VICH1PPSETR_VC(x) ((x) << 22)
+
+/* Video-Input Channel 1 Vertical Size Set Register */
+#define VICH1VSSETR 0x428
+#define VICH1VSSETR_VACTIVE(x) (((x) & 0x7fff) << 16)
+#define VICH1VSSETR_VSPOL_LOW (1 << 15)
+#define VICH1VSSETR_VSPOL_HIGH (0 << 15)
+#define VICH1VSSETR_VSA(x) (((x) & 0xfff) << 0)
+
+/* Video-Input Channel 1 Vertical Porch Set Register */
+#define VICH1VPSETR 0x42c
+#define VICH1VPSETR_VFP(x) (((x) & 0x1fff) << 16)
+#define VICH1VPSETR_VBP(x) (((x) & 0x1fff) << 0)
+
+/* Video-Input Channel 1 Horizontal Size Set Register */
+#define VICH1HSSETR 0x430
+#define VICH1HSSETR_HACTIVE(x) (((x) & 0x7fff) << 16)
+#define VICH1HSSETR_HSPOL_LOW (1 << 15)
+#define VICH1HSSETR_HSPOL_HIGH (0 << 15)
+#define VICH1HSSETR_HSA(x) (((x) & 0xfff) << 0)
+
+/* Video-Input Channel 1 Horizontal Porch Set Register */
+#define VICH1HPSETR 0x434
+#define VICH1HPSETR_HFP(x) (((x) & 0x1fff) << 16)
+#define VICH1HPSETR_HBP(x) (((x) & 0x1fff) << 0)
+
+#endif /* __RZG2L_MIPI_DSI_REGS_H__ */
diff --git a/drivers/gpu/drm/tegra/fbdev.c b/drivers/gpu/drm/tegra/fbdev.c
index db6eaac3d30e..08cd471e5aa2 100644
--- a/drivers/gpu/drm/tegra/fbdev.c
+++ b/drivers/gpu/drm/tegra/fbdev.c
@@ -72,10 +72,9 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
struct tegra_drm *tegra = helper->dev->dev_private;
struct drm_device *drm = helper->dev;
struct drm_mode_fb_cmd2 cmd = { 0 };
+ struct fb_info *info = helper->info;
unsigned int bytes_per_pixel;
struct drm_framebuffer *fb;
- unsigned long offset;
- struct fb_info *info;
struct tegra_bo *bo;
size_t size;
int err;
@@ -96,13 +95,6 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
if (IS_ERR(bo))
return PTR_ERR(bo);
- info = drm_fb_helper_alloc_info(helper);
- if (IS_ERR(info)) {
- dev_err(drm->dev, "failed to allocate framebuffer info\n");
- drm_gem_object_put(&bo->gem);
- return PTR_ERR(info);
- }
-
fb = tegra_fb_alloc(drm, &cmd, &bo, 1);
if (IS_ERR(fb)) {
err = PTR_ERR(fb);
@@ -113,15 +105,11 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
}
helper->fb = fb;
- helper->info = info;
info->fbops = &tegra_fb_ops;
drm_fb_helper_fill_info(info, helper, sizes);
- offset = info->var.xoffset * bytes_per_pixel +
- info->var.yoffset * fb->pitches[0];
-
if (bo->pages) {
bo->vaddr = vmap(bo->pages, bo->num_pages, VM_MAP,
pgprot_writecombine(PAGE_KERNEL));
@@ -133,9 +121,9 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
}
info->flags |= FBINFO_VIRTFB;
- info->screen_buffer = bo->vaddr + offset;
+ info->screen_buffer = bo->vaddr;
info->screen_size = size;
- info->fix.smem_start = (unsigned long)(bo->iova + offset);
+ info->fix.smem_start = (unsigned long)(bo->iova);
info->fix.smem_len = size;
return 0;
diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c
index 563b3dfeb9b9..82ec892d3b5c 100644
--- a/drivers/gpu/drm/vc4/vc4_irq.c
+++ b/drivers/gpu/drm/vc4/vc4_irq.c
@@ -104,7 +104,7 @@ vc4_overflow_mem_work(struct work_struct *work)
vc4->bin_alloc_overflow = BIT(bin_bo_slot);
V3D_WRITE(V3D_BPOA, bo->base.dma_addr + bin_bo_slot * vc4->bin_alloc_size);
- V3D_WRITE(V3D_BPOS, bo->base.base.size);
+ V3D_WRITE(V3D_BPOS, vc4->bin_alloc_size);
V3D_WRITE(V3D_INTCTL, V3D_INT_OUTOMEM);
V3D_WRITE(V3D_INTENA, V3D_INT_OUTOMEM);
spin_unlock_irqrestore(&vc4->job_lock, irqflags);
diff --git a/drivers/gpu/drm/vc4/vc4_validate.c b/drivers/gpu/drm/vc4/vc4_validate.c
index 7dff3ca5af6b..71830f1f04f8 100644
--- a/drivers/gpu/drm/vc4/vc4_validate.c
+++ b/drivers/gpu/drm/vc4/vc4_validate.c
@@ -387,6 +387,23 @@ validate_tile_binning_config(VALIDATE_ARGS)
return -EINVAL;
}
+ /* The tile state data array is 48 bytes per tile, and we put it at
+ * the start of a BO containing both it and the tile alloc.
+ */
+ tile_state_size = 48 * tile_count;
+
+ /* Since the tile alloc array will follow us, align. */
+ tile_state_size = roundup(tile_state_size, 4096);
+
+ /* Reject configurations whose tile state would leave no room for
+ * the tile alloc pool that follows it in the slot.
+ */
+ if (tile_state_size >= vc4->bin_alloc_size) {
+ DRM_DEBUG("Tile binning config of %dx%d too large\n",
+ exec->bin_tiles_x, exec->bin_tiles_y);
+ return -EINVAL;
+ }
+
bin_slot = vc4_v3d_get_bin_slot(vc4);
if (bin_slot < 0) {
if (bin_slot != -EINTR && bin_slot != -ERESTARTSYS) {
@@ -402,13 +419,13 @@ validate_tile_binning_config(VALIDATE_ARGS)
exec->bin_slots |= BIT(bin_slot);
bin_addr = vc4->bin_bo->base.dma_addr + bin_slot * vc4->bin_alloc_size;
- /* The tile state data array is 48 bytes per tile, and we put it at
- * the start of a BO containing both it and the tile alloc.
- */
- tile_state_size = 48 * tile_count;
+ exec->tile_alloc_offset = bin_addr + tile_state_size;
- /* Since the tile alloc array will follow us, align. */
- exec->tile_alloc_offset = bin_addr + roundup(tile_state_size, 4096);
+ /* The TSDA area must be zeroed out before use, otherwise the PTB might
+ * consume a stale tile state.
+ */
+ memset(vc4->bin_bo->base.vaddr + bin_slot * vc4->bin_alloc_size, 0,
+ tile_state_size);
*(uint8_t *)(validated + 14) =
((flags & ~(VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_MASK |
diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.c b/drivers/gpu/drm/vmwgfx/ttm_object.c
index ddf8373c1d77..f6b59f7db461 100644
--- a/drivers/gpu/drm/vmwgfx/ttm_object.c
+++ b/drivers/gpu/drm/vmwgfx/ttm_object.c
@@ -551,14 +551,17 @@ int ttm_prime_fd_to_handle(struct ttm_object_file *tfile,
if (IS_ERR(dma_buf))
return PTR_ERR(dma_buf);
- if (dma_buf->ops != &tdev->ops)
- return -ENOSYS;
+ if (dma_buf->ops != &tdev->ops) {
+ ret = -ENOSYS;
+ goto out;
+ }
prime = (struct ttm_prime_object *) dma_buf->priv;
base = &prime->base;
*handle = base->handle;
ret = ttm_ref_object_add(tfile, base, NULL, false);
+out:
dma_buf_put(dma_buf);
return ret;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
index 890a66a2361f..04c5141b7c62 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
@@ -30,6 +30,7 @@
#include "vmwgfx_bo.h"
#include <linux/highmem.h>
+#include <linux/overflow.h>
/*
* Template that implements find_first_diff() for a generic
@@ -463,19 +464,42 @@ static int vmw_external_bo_copy(struct vmw_bo *dst, u32 dst_offset,
container_of(dst->tbo.bdev, struct vmw_private, bdev);
size_t dst_size = dst->tbo.resource->size;
size_t src_size = src->tbo.resource->size;
+ size_t dst_end, src_end;
struct iosys_map dst_map = {0};
struct iosys_map src_map = {0};
+ bool dst_mapped = false;
+ bool src_mapped = false;
int ret, i;
int x_in_bytes;
u8 *vsrc;
u8 *vdst;
+ if (!height || !width_in_bytes)
+ return 0;
+
+ if (!dst_stride || !src_stride)
+ return -EINVAL;
+ if (dst_stride < width_in_bytes || src_stride < width_in_bytes)
+ return -EINVAL;
+ if (check_mul_overflow((size_t)dst_stride, (size_t)height - 1, &dst_end) ||
+ check_add_overflow(dst_end, (size_t)width_in_bytes, &dst_end) ||
+ check_add_overflow((size_t)dst_offset, dst_end, &dst_end) ||
+ dst_end > dst_size ||
+ check_mul_overflow((size_t)src_stride, (size_t)height - 1, &src_end) ||
+ check_add_overflow(src_end, (size_t)width_in_bytes, &src_end) ||
+ check_add_overflow((size_t)src_offset, src_end, &src_end) ||
+ src_end > src_size) {
+ drm_dbg_driver(&vmw->drm, "Out-of-bounds external BO copy\n");
+ return -EINVAL;
+ }
+
vsrc = map_external(src, &src_map);
if (!vsrc) {
drm_dbg_driver(&vmw->drm, "Wasn't able to map src\n");
ret = -ENOMEM;
goto out;
}
+ src_mapped = true;
vdst = map_external(dst, &dst_map);
if (!vdst) {
@@ -483,16 +507,13 @@ static int vmw_external_bo_copy(struct vmw_bo *dst, u32 dst_offset,
ret = -ENOMEM;
goto out;
}
+ dst_mapped = true;
vsrc += src_offset;
vdst += dst_offset;
- if (src_stride == dst_stride) {
- dst_size -= dst_offset;
- src_size -= src_offset;
- memcpy(vdst, vsrc,
- min(dst_stride * height, min(dst_size, src_size)));
+ if (src_stride == dst_stride && width_in_bytes == dst_stride) {
+ memcpy(vdst, vsrc, dst_stride * (size_t)height);
} else {
- WARN_ON(dst_stride < width_in_bytes);
for (i = 0; i < height; ++i) {
memcpy(vdst, vsrc, width_in_bytes);
vsrc += src_stride;
@@ -508,8 +529,10 @@ static int vmw_external_bo_copy(struct vmw_bo *dst, u32 dst_offset,
ret = 0;
out:
- unmap_external(src, &src_map);
- unmap_external(dst, &dst_map);
+ if (src_mapped)
+ unmap_external(src, &src_map);
+ if (dst_mapped)
+ unmap_external(dst, &dst_map);
return ret;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 073791d69629..1e54d847da82 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -1289,9 +1289,13 @@ static int vmw_cmd_dx_bind_query(struct vmw_private *dev_priv,
SVGA3dCmdHeader *header)
{
VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXBindQuery);
+ struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context);
struct vmw_bo *vmw_bo;
int ret;
+ if (!ctx_node)
+ return -EINVAL;
+
cmd = container_of(header, typeof(*cmd), header);
/*
@@ -1305,7 +1309,7 @@ static int vmw_cmd_dx_bind_query(struct vmw_private *dev_priv,
return ret;
sw_context->dx_query_mob = vmw_bo;
- sw_context->dx_query_ctx = sw_context->dx_ctx_node->ctx;
+ sw_context->dx_query_ctx = ctx_node->ctx;
return 0;
}
@@ -1523,6 +1527,12 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
bool dirty;
cmd = container_of(header, typeof(*cmd), header);
+
+ if (unlikely(header->size < sizeof(cmd->body) + sizeof(*suffix))) {
+ VMW_DEBUG_USER("Illegal SVGA_3D_CMD_SURFACE_DMA size.\n");
+ return -EINVAL;
+ }
+
suffix = (SVGA3dCmdSurfaceDMASuffix *)((unsigned long) &cmd->body +
header->size - sizeof(*suffix));
@@ -1584,11 +1594,17 @@ static int vmw_cmd_draw(struct vmw_private *dev_priv,
uint32_t maxnum;
int ret;
+ cmd = container_of(header, typeof(*cmd), header);
+
+ if (unlikely(header->size < sizeof(cmd->body))) {
+ VMW_DEBUG_USER("Illegal DRAW_PRIMITIVES header size.\n");
+ return -EINVAL;
+ }
+
ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
if (unlikely(ret != 0))
return ret;
- cmd = container_of(header, typeof(*cmd), header);
maxnum = (header->size - sizeof(cmd->body)) / sizeof(*decl);
if (unlikely(cmd->body.numVertexDecls > maxnum)) {
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index ca300c7427d2..2f61b1100788 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -134,7 +134,7 @@ static void vmw_resource_release(struct kref *kref)
val_buf.num_shared = 0;
res->func->unbind(res, false, &val_buf);
}
- res->guest_memory_size = false;
+ res->guest_memory_dirty = false;
vmw_resource_mob_detach(res);
if (res->dirty)
res->func->dirty_free(res);
@@ -764,7 +764,7 @@ void vmw_resource_unbind_list(struct vmw_bo *vbo)
if (!WARN_ON_ONCE(!res->func->unbind))
(void) res->func->unbind(res, res->res_dirty, &val_buf);
- res->guest_memory_size = true;
+ res->guest_memory_dirty = true;
res->res_dirty = false;
vmw_resource_mob_detach(res);
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
index a8c8c9375d29..bc89a137ab6d 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
@@ -25,6 +25,8 @@
*
**************************************************************************/
+#include <linux/overflow.h>
+
#include <drm/ttm/ttm_placement.h>
#include "vmwgfx_binding.h"
@@ -685,7 +687,7 @@ int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data,
static int vmw_user_shader_alloc(struct vmw_private *dev_priv,
struct vmw_bo *buffer,
size_t shader_size,
- size_t offset,
+ u64 offset,
SVGA3dShaderType shader_type,
uint8_t num_input_sig,
uint8_t num_output_sig,
@@ -739,7 +741,7 @@ static int vmw_user_shader_alloc(struct vmw_private *dev_priv,
static struct vmw_resource *vmw_shader_alloc(struct vmw_private *dev_priv,
struct vmw_bo *buffer,
size_t shader_size,
- size_t offset,
+ u64 offset,
SVGA3dShaderType shader_type)
{
struct vmw_shader *shader;
@@ -768,7 +770,7 @@ static struct vmw_resource *vmw_shader_alloc(struct vmw_private *dev_priv,
static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv,
enum drm_vmw_shader_type shader_type_drm,
- u32 buffer_handle, size_t size, size_t offset,
+ u32 buffer_handle, size_t size, u64 offset,
uint8_t num_input_sig, uint8_t num_output_sig,
uint32_t *shader_handle)
{
@@ -779,13 +781,16 @@ static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv,
int ret;
if (buffer_handle != SVGA3D_INVALID_ID) {
+ u64 end;
+
ret = vmw_user_bo_lookup(file_priv, buffer_handle, &buffer);
if (unlikely(ret != 0)) {
VMW_DEBUG_USER("Couldn't find buffer for shader creation.\n");
return ret;
}
- if ((u64)buffer->tbo.base.size < (u64)size + (u64)offset) {
+ if (check_add_overflow((u64)size, (u64)offset, &end) ||
+ end > buffer->tbo.base.size) {
VMW_DEBUG_USER("Illegal buffer- or shader size.\n");
ret = -EINVAL;
goto out_bad_arg;
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 84ad70c9d038..d23d7e208aa7 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -1749,7 +1749,8 @@ static int logi_dj_raw_event(struct hid_device *hdev,
static int logi_dj_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
- struct hid_report_enum *rep_enum;
+ struct hid_report_enum *input_report_enum;
+ struct hid_report_enum *output_report_enum;
struct hid_report *rep;
struct dj_receiver_dev *djrcv_dev;
struct usb_interface *intf;
@@ -1793,10 +1794,25 @@ static int logi_dj_probe(struct hid_device *hdev,
}
}
- rep_enum = &hdev->report_enum[HID_INPUT_REPORT];
+ output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT];
+ rep = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT];
+
+ if (rep && rep->maxfield < 1) {
+ hid_err(hdev, "Expected size of DJ short report is %d, but got 0",
+ DJREPORT_SHORT_LENGTH - 1);
+ return -EINVAL;
+ }
+
+ if (rep && rep->field[0]->report_count != DJREPORT_SHORT_LENGTH - 1) {
+ hid_err(hdev, "Expected size of DJ short report is %d, but got %d",
+ DJREPORT_SHORT_LENGTH - 1, rep->field[0]->report_count);
+ return -EINVAL;
+ }
+
+ input_report_enum = &hdev->report_enum[HID_INPUT_REPORT];
/* no input reports, bail out */
- if (list_empty(&rep_enum->report_list))
+ if (list_empty(&input_report_enum->report_list))
return -ENODEV;
/*
@@ -1804,7 +1820,7 @@ static int logi_dj_probe(struct hid_device *hdev,
* Note: we should theoretically check for HID++ and DJ
* collections, but this will do.
*/
- list_for_each_entry(rep, &rep_enum->report_list, list) {
+ list_for_each_entry(rep, &input_report_enum->report_list, list) {
if (rep->application == 0xff000001)
has_hidpp = true;
}
@@ -1817,7 +1833,7 @@ static int logi_dj_probe(struct hid_device *hdev,
return -ENODEV;
/* get the current application attached to the node */
- rep = list_first_entry(&rep_enum->report_list, struct hid_report, list);
+ rep = list_first_entry(&input_report_enum->report_list, struct hid_report, list);
djrcv_dev = dj_get_receiver_dev(hdev, id->driver_data,
rep->application, has_hidpp);
if (!djrcv_dev) {
@@ -1825,7 +1841,7 @@ static int logi_dj_probe(struct hid_device *hdev,
return -ENOMEM;
}
- if (!rep_enum->numbered)
+ if (!input_report_enum->numbered)
djrcv_dev->unnumbered_application = rep->application;
/* Starts the usb device and connects to upper interfaces hiddev and
diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c
index c4b3a4a18670..3ced54988f54 100644
--- a/drivers/hwmon/adt7470.c
+++ b/drivers/hwmon/adt7470.c
@@ -70,8 +70,8 @@ static const unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END };
#define ADT7470_PWM1_AUTO_MASK 0x80
#define ADT7470_PWM_AUTO_MASK 0xC0
#define ADT7470_REG_PWM34_CFG 0x69
-#define ADT7470_PWM3_AUTO_MASK 0x40
-#define ADT7470_PWM4_AUTO_MASK 0x80
+#define ADT7470_PWM4_AUTO_MASK 0x40
+#define ADT7470_PWM3_AUTO_MASK 0x80
#define ADT7470_REG_PWM_MIN_BASE_ADDR 0x6A
#define ADT7470_REG_PWM_MIN_MAX_ADDR 0x6D
#define ADT7470_REG_PWM_TEMP_MIN_BASE_ADDR 0x6E
@@ -110,6 +110,21 @@ static const unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END };
#define ALARM2(x) ((x) << 8)
+/* TEMP1..TEMP7 (ch 0..6) are, respectively BIT(0)..BIT(6) of reg 0x41 and
+ * 0x72, or BIT(0)..BIT(6) of data->alarm.
+ * TEMP8..TEMP9 (ch 7..9) are, respectively BIT(0)..BIT(2) of reg 0x42 and
+ * 0x73, or BIT(8)..BIT(10) of data->alarm.
+ */
+#define TEMP_ALARM_BIT(ch) ({ \
+ typeof(ch) _ch = (ch); \
+ (1 << (_ch < 7 ? _ch : _ch + 1)); \
+})
+
+/* FAN1..FAN4 (ch 0..3) are respectively BIT(4)..BIT(7) in
+ * reg 0x42 and 0x73 or BIT(12)..BIT(15) in data->alarm.
+ */
+#define FAN_ALARM_BIT(ch) (1 << (12 + (ch)))
+
#define ADT7470_VENDOR 0x41
#define ADT7470_DEVICE 0x70
/* datasheet only mentions a revision 2 */
@@ -167,6 +182,7 @@ struct adt7470_data {
u8 pwm_min[ADT7470_PWM_COUNT];
s8 pwm_tmin[ADT7470_PWM_COUNT];
u8 pwm_auto_temp[ADT7470_PWM_COUNT];
+ u32 pwm_freq;
struct task_struct *auto_update;
unsigned int auto_update_interval;
@@ -205,11 +221,12 @@ static inline int adt7470_write_word_data(struct adt7470_data *data, unsigned in
/* Probe for temperature sensors. Assumes lock is held */
static int adt7470_read_temperatures(struct adt7470_data *data)
{
- unsigned long res;
+ struct device *dev = regmap_get_device(data->regmap);
+ u8 pwm[ADT7470_FAN_COUNT];
unsigned int pwm_cfg[2];
- int err;
+ unsigned long res;
+ int err, err2;
int i;
- u8 pwm[ADT7470_FAN_COUNT];
/* save pwm[1-4] config register */
err = regmap_read(data->regmap, ADT7470_REG_PWM_CFG(0), &pwm_cfg[0]);
@@ -233,19 +250,19 @@ static int adt7470_read_temperatures(struct adt7470_data *data)
err = regmap_update_bits(data->regmap, ADT7470_REG_PWM_CFG(2),
ADT7470_PWM_AUTO_MASK, 0);
if (err < 0)
- return err;
+ goto out_restore;
/* write pwm control to whatever it was */
err = regmap_bulk_write(data->regmap, ADT7470_REG_PWM(0), &pwm[0],
ADT7470_PWM_COUNT);
if (err < 0)
- return err;
+ goto out_restore;
/* start reading temperature sensors */
err = regmap_update_bits(data->regmap, ADT7470_REG_CFG,
ADT7470_T05_STB_MASK, ADT7470_T05_STB_MASK);
if (err < 0)
- return err;
+ goto out_restore;
/* Delay is 200ms * number of temp sensors. */
res = msleep_interruptible((data->num_temp_sensors >= 0 ?
@@ -256,13 +273,30 @@ static int adt7470_read_temperatures(struct adt7470_data *data)
err = regmap_update_bits(data->regmap, ADT7470_REG_CFG,
ADT7470_T05_STB_MASK, 0);
if (err < 0)
- return err;
+ goto out_restore;
+out_restore:
/* restore pwm[1-4] config registers */
- err = regmap_write(data->regmap, ADT7470_REG_PWM_CFG(0), pwm_cfg[0]);
- if (err < 0)
- return err;
- err = regmap_write(data->regmap, ADT7470_REG_PWM_CFG(2), pwm_cfg[1]);
+ err2 = regmap_write(data->regmap, ADT7470_REG_PWM_CFG(0), pwm_cfg[0]);
+ if (err2 < 0) {
+ dev_warn_ratelimited(dev,
+ "failed to restore PWM{1,2} config (%d)\n",
+ err2);
+
+ if (!err)
+ err = err2;
+ }
+
+ err2 = regmap_write(data->regmap, ADT7470_REG_PWM_CFG(2), pwm_cfg[1]);
+ if (err2 < 0) {
+ dev_warn_ratelimited(dev,
+ "failed to restore PWM{3,4} config (%d)\n",
+ err2);
+
+ if (!err)
+ err = err2;
+ }
+
if (err < 0)
return err;
@@ -491,7 +525,7 @@ static ssize_t auto_update_interval_store(struct device *dev,
if (kstrtol(buf, 10, &temp))
return -EINVAL;
- temp = clamp_val(temp, 0, 60000);
+ temp = clamp_val(temp, 500, 60000);
mutex_lock(&data->lock);
data->auto_update_interval = temp;
@@ -551,7 +585,7 @@ static int adt7470_temp_read(struct device *dev, u32 attr, int channel, long *va
*val = 1000 * data->temp_max[channel];
break;
case hwmon_temp_alarm:
- *val = !!(data->alarm & channel);
+ *val = !!(data->alarm & TEMP_ALARM_BIT(channel));
break;
default:
return -EOPNOTSUPP;
@@ -571,14 +605,16 @@ static int adt7470_temp_write(struct device *dev, u32 attr, int channel, long va
switch (attr) {
case hwmon_temp_min:
mutex_lock(&data->lock);
- data->temp_min[channel] = val;
err = regmap_write(data->regmap, ADT7470_TEMP_MIN_REG(channel), val);
+ if (!err)
+ data->temp_min[channel] = val;
mutex_unlock(&data->lock);
break;
case hwmon_temp_max:
mutex_lock(&data->lock);
- data->temp_max[channel] = val;
err = regmap_write(data->regmap, ADT7470_TEMP_MAX_REG(channel), val);
+ if (!err)
+ data->temp_max[channel] = val;
mutex_unlock(&data->lock);
break;
default:
@@ -624,36 +660,33 @@ static ssize_t alarm_mask_store(struct device *dev,
static int adt7470_fan_read(struct device *dev, u32 attr, int channel, long *val)
{
struct adt7470_data *data = adt7470_update_device(dev);
+ u16 fan_data;
if (IS_ERR(data))
return PTR_ERR(data);
switch (attr) {
case hwmon_fan_input:
- if (FAN_DATA_VALID(data->fan[channel]))
- *val = FAN_PERIOD_TO_RPM(data->fan[channel]);
- else
- *val = 0;
+ fan_data = READ_ONCE(data->fan[channel]);
break;
case hwmon_fan_min:
- if (FAN_DATA_VALID(data->fan_min[channel]))
- *val = FAN_PERIOD_TO_RPM(data->fan_min[channel]);
- else
- *val = 0;
+ fan_data = READ_ONCE(data->fan_min[channel]);
break;
case hwmon_fan_max:
- if (FAN_DATA_VALID(data->fan_max[channel]))
- *val = FAN_PERIOD_TO_RPM(data->fan_max[channel]);
- else
- *val = 0;
+ fan_data = READ_ONCE(data->fan_max[channel]);
break;
case hwmon_fan_alarm:
- *val = !!(data->alarm & (1 << (12 + channel)));
- break;
+ *val = !!(data->alarm & FAN_ALARM_BIT(channel));
+ return 0;
default:
return -EOPNOTSUPP;
}
+ if (FAN_DATA_VALID(fan_data))
+ *val = FAN_PERIOD_TO_RPM(fan_data);
+ else
+ *val = 0;
+
return 0;
}
@@ -721,7 +754,7 @@ static ssize_t force_pwm_max_store(struct device *dev,
}
/* These are the valid PWM frequencies to the nearest Hz */
-static const int adt7470_freq_map[] = {
+static const u32 adt7470_freq_map[] = {
11, 15, 22, 29, 35, 44, 59, 88, 1400, 22500
};
@@ -769,7 +802,7 @@ static int adt7470_pwm_read(struct device *dev, u32 attr, int channel, long *val
*val = 1 + data->pwm_automatic[channel];
break;
case hwmon_pwm_freq:
- *val = pwm1_freq_get(dev);
+ *val = data->pwm_freq;
break;
default:
return -EOPNOTSUPP;
@@ -782,12 +815,14 @@ static int pwm1_freq_set(struct device *dev, long freq)
{
struct adt7470_data *data = dev_get_drvdata(dev);
unsigned int low_freq = ADT7470_CFG_LF;
+ u32 closest_freq;
int index;
int err;
/* Round the user value given to the closest available frequency */
index = find_closest(freq, adt7470_freq_map,
ARRAY_SIZE(adt7470_freq_map));
+ closest_freq = adt7470_freq_map[index];
if (index >= 8) {
index -= 8;
@@ -805,6 +840,10 @@ static int pwm1_freq_set(struct device *dev, long freq)
err = regmap_update_bits(data->regmap, ADT7470_REG_CFG_2,
ADT7470_FREQ_MASK,
index << ADT7470_FREQ_SHIFT);
+ if (err < 0)
+ goto out;
+
+ data->pwm_freq = closest_freq;
out:
mutex_unlock(&data->lock);
@@ -821,9 +860,10 @@ static int adt7470_pwm_write(struct device *dev, u32 attr, int channel, long val
case hwmon_pwm_input:
val = clamp_val(val, 0, 255);
mutex_lock(&data->lock);
- data->pwm[channel] = val;
err = regmap_write(data->regmap, ADT7470_REG_PWM(channel),
- data->pwm[channel]);
+ val);
+ if (!err)
+ data->pwm[channel] = val;
mutex_unlock(&data->lock);
break;
case hwmon_pwm_enable:
@@ -837,10 +877,11 @@ static int adt7470_pwm_write(struct device *dev, u32 attr, int channel, long val
val--;
mutex_lock(&data->lock);
- data->pwm_automatic[channel] = val;
err = regmap_update_bits(data->regmap, ADT7470_REG_PWM_CFG(channel),
pwm_auto_reg_mask,
val ? pwm_auto_reg_mask : 0);
+ if (!err)
+ data->pwm_automatic[channel] = val;
mutex_unlock(&data->lock);
break;
case hwmon_pwm_freq:
@@ -1016,8 +1057,10 @@ static ssize_t pwm_auto_temp_store(struct device *dev,
if (temp < 0)
return temp;
+ if (temp > 0xF)
+ return -EINVAL;
+
mutex_lock(&data->lock);
- data->pwm_automatic[attr->index] = temp;
if (!(attr->index % 2)) {
mask = 0xF0;
@@ -1028,6 +1071,9 @@ static ssize_t pwm_auto_temp_store(struct device *dev,
}
err = regmap_update_bits(data->regmap, pwm_auto_reg, mask, val);
+ if (!err)
+ data->pwm_auto_temp[attr->index] = temp;
+
mutex_unlock(&data->lock);
return err < 0 ? err : count;
@@ -1256,6 +1302,7 @@ static int adt7470_probe(struct i2c_client *client)
struct device *dev = &client->dev;
struct adt7470_data *data;
struct device *hwmon_dev;
+ int freq_val;
int err;
data = devm_kzalloc(dev, sizeof(struct adt7470_data), GFP_KERNEL);
@@ -1280,6 +1327,14 @@ static int adt7470_probe(struct i2c_client *client)
if (err < 0)
return err;
+ freq_val = pwm1_freq_get(dev);
+ if (freq_val <= 0) {
+ err = freq_val < 0 ? freq_val : -EINVAL;
+ return err;
+ }
+
+ data->pwm_freq = (u32)freq_val;
+
/* Register sysfs hooks */
hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, data,
&adt7470_chip_info,
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index e0d7454a301c..7be9874b3dfb 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -1149,7 +1149,7 @@ static int lm90_update_alarms_locked(struct lm90_data *data, bool force)
check_enable = (client->irq || !(data->config_orig & 0x80)) &&
(data->config & 0x80);
- if (force || check_enable)
+ if (data->hwmon_dev && (force || check_enable))
schedule_work(&data->report_work);
/*
@@ -1157,7 +1157,7 @@ static int lm90_update_alarms_locked(struct lm90_data *data, bool force)
* alarms are all clear, and alerts are currently disabled.
* Otherwise (re)schedule worker if needed.
*/
- if (check_enable) {
+ if (check_enable && data->hwmon_dev) {
if (!(data->current_alarms & data->alert_alarms)) {
dev_dbg(&client->dev, "Re-enabling ALERT#\n");
lm90_update_confreg(data, data->config & ~0x80);
diff --git a/drivers/hwmon/nct6775-core.c b/drivers/hwmon/nct6775-core.c
index da4c3425d2d1..6d28cf101f5f 100644
--- a/drivers/hwmon/nct6775-core.c
+++ b/drivers/hwmon/nct6775-core.c
@@ -791,12 +791,12 @@ static const u16 NCT6106_REG_TOLERANCE_H[] = { 0x112, 0x122, 0x132 };
static const u16 NCT6106_REG_TARGET[] = { 0x111, 0x121, 0x131 };
-static const u16 NCT6106_REG_WEIGHT_TEMP_SEL[] = { 0x168, 0x178, 0x188 };
-static const u16 NCT6106_REG_WEIGHT_TEMP_STEP[] = { 0x169, 0x179, 0x189 };
-static const u16 NCT6106_REG_WEIGHT_TEMP_STEP_TOL[] = { 0x16a, 0x17a, 0x18a };
-static const u16 NCT6106_REG_WEIGHT_DUTY_STEP[] = { 0x16b, 0x17b, 0x18b };
-static const u16 NCT6106_REG_WEIGHT_TEMP_BASE[] = { 0x16c, 0x17c, 0x18c };
-static const u16 NCT6106_REG_WEIGHT_DUTY_BASE[] = { 0x16d, 0x17d, 0x18d };
+static const u16 NCT6106_REG_WEIGHT_TEMP_SEL[] = { 0x168, 0x178, 0x188, 0, 0 };
+static const u16 NCT6106_REG_WEIGHT_TEMP_STEP[] = { 0x169, 0x179, 0x189, 0, 0 };
+static const u16 NCT6106_REG_WEIGHT_TEMP_STEP_TOL[] = { 0x16a, 0x17a, 0x18a, 0, 0 };
+static const u16 NCT6106_REG_WEIGHT_DUTY_STEP[] = { 0x16b, 0x17b, 0x18b, 0, 0 };
+static const u16 NCT6106_REG_WEIGHT_TEMP_BASE[] = { 0x16c, 0x17c, 0x18c, 0, 0 };
+static const u16 NCT6106_REG_WEIGHT_DUTY_BASE[] = { 0x16d, 0x17d, 0x18d, 0, 0 };
static const u16 NCT6106_REG_AUTO_TEMP[] = { 0x160, 0x170, 0x180 };
static const u16 NCT6106_REG_AUTO_PWM[] = { 0x164, 0x174, 0x184 };
@@ -846,8 +846,6 @@ static const u16 NCT6116_FAN_PULSE_SHIFT[] = { 0, 2, 4, 6, 6 };
static const u16 NCT6116_REG_PWM[] = { 0x119, 0x129, 0x139, 0x199, 0x1a9 };
static const u16 NCT6116_REG_FAN_MODE[] = { 0x113, 0x123, 0x133, 0x193, 0x1a3 };
static const u16 NCT6116_REG_TEMP_SEL[] = { 0x110, 0x120, 0x130, 0x190, 0x1a0 };
-static const u16 NCT6116_REG_TEMP_SOURCE[] = {
- 0xb0, 0xb1, 0xb2 };
static const u16 NCT6116_REG_CRITICAL_TEMP[] = {
0x11a, 0x12a, 0x13a, 0x19a, 0x1aa };
@@ -3650,7 +3648,7 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
= NCT6106_CRITICAL_PWM_ENABLE_MASK;
data->REG_CRITICAL_PWM = NCT6116_REG_CRITICAL_PWM;
data->REG_TEMP_OFFSET = NCT6106_REG_TEMP_OFFSET;
- data->REG_TEMP_SOURCE = NCT6116_REG_TEMP_SOURCE;
+ data->REG_TEMP_SOURCE = NCT6106_REG_TEMP_SOURCE;
data->REG_TEMP_SEL = NCT6116_REG_TEMP_SEL;
data->REG_WEIGHT_TEMP_SEL = NCT6106_REG_WEIGHT_TEMP_SEL;
data->REG_WEIGHT_TEMP[0] = NCT6106_REG_WEIGHT_TEMP_STEP;
@@ -3664,13 +3662,13 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
reg_temp = NCT6106_REG_TEMP;
reg_temp_mon = NCT6106_REG_TEMP_MON;
- num_reg_temp = ARRAY_SIZE(NCT6106_REG_TEMP);
+ num_reg_temp = 3;
num_reg_temp_mon = ARRAY_SIZE(NCT6106_REG_TEMP_MON);
num_reg_tsi_temp = ARRAY_SIZE(NCT6116_REG_TSI_TEMP);
reg_temp_over = NCT6106_REG_TEMP_OVER;
reg_temp_hyst = NCT6106_REG_TEMP_HYST;
reg_temp_config = NCT6106_REG_TEMP_CONFIG;
- num_reg_temp_config = ARRAY_SIZE(NCT6106_REG_TEMP_CONFIG);
+ num_reg_temp_config = 3;
reg_temp_alternate = NCT6106_REG_TEMP_ALTERNATE;
reg_temp_crit = NCT6106_REG_TEMP_CRIT;
reg_temp_crit_l = NCT6106_REG_TEMP_CRIT_L;
diff --git a/drivers/hwmon/npcm750-pwm-fan.c b/drivers/hwmon/npcm750-pwm-fan.c
index 10ed3f4335d4..5c46afe41094 100644
--- a/drivers/hwmon/npcm750-pwm-fan.c
+++ b/drivers/hwmon/npcm750-pwm-fan.c
@@ -360,6 +360,11 @@ static void npcm7xx_fan_polling(struct timer_list *t)
add_timer(&data->fan_timer);
}
+static void npcm7xx_fan_cleanup(void *timer)
+{
+ timer_shutdown_sync(timer);
+}
+
static inline void npcm7xx_fan_compute(struct npcm7xx_pwm_fan_data *data,
u8 fan, u8 cmp, u8 fan_id, u8 flag_int,
u8 flag_mode, u8 flag_clear)
@@ -1003,6 +1008,12 @@ static int npcm7xx_pwm_fan_probe(struct platform_device *pdev)
msecs_to_jiffies(NPCM7XX_FAN_POLL_TIMER_200MS);
timer_setup(&data->fan_timer,
npcm7xx_fan_polling, 0);
+ ret = devm_add_action_or_reset(dev,
+ npcm7xx_fan_cleanup,
+ &data->fan_timer);
+ if (ret)
+ return ret;
+
add_timer(&data->fan_timer);
break;
}
diff --git a/drivers/hwmon/nzxt-smart2.c b/drivers/hwmon/nzxt-smart2.c
index 0ce956954378..5bbe6f3f8af4 100644
--- a/drivers/hwmon/nzxt-smart2.c
+++ b/drivers/hwmon/nzxt-smart2.c
@@ -203,7 +203,7 @@ struct drvdata {
*/
struct mutex mutex;
long update_interval;
- u8 output_buffer[OUTPUT_REPORT_SIZE];
+ u8 output_buffer[OUTPUT_REPORT_SIZE] __aligned(ARCH_DMA_MINALIGN);
};
static long scale_pwm_value(long val, long orig_max, long new_max)
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index eafeabfd93d7..3641816caed1 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -449,7 +449,7 @@ int pmbus_update_byte_data(struct i2c_client *client, int page, u8 reg,
if (tmp != rv)
rv = _pmbus_write_byte_data(client, page, reg, tmp);
- return rv;
+ return rv < 0 ? rv : 0;
}
EXPORT_SYMBOL_NS_GPL(pmbus_update_byte_data, PMBUS);
@@ -2803,8 +2803,9 @@ static void pmbus_notify(struct pmbus_data *data, int page, int reg, int flags)
if (reg == sreg && page == spage && (smask & flags)) {
dev_dbg(data->dev, "sysfs notify: %s", da->attr.name);
- sysfs_notify(&data->dev->kobj, NULL, da->attr.name);
- kobject_uevent(&data->dev->kobj, KOBJ_CHANGE);
+ sysfs_notify(&data->hwmon_dev->kobj, NULL,
+ da->attr.name);
+ kobject_uevent(&data->hwmon_dev->kobj, KOBJ_CHANGE);
flags &= ~smask;
}
diff --git a/drivers/i2c/busses/i2c-amd-mp2-plat.c b/drivers/i2c/busses/i2c-amd-mp2-plat.c
index 112fe2bc5662..bebe75267aa6 100644
--- a/drivers/i2c/busses/i2c-amd-mp2-plat.c
+++ b/drivers/i2c/busses/i2c-amd-mp2-plat.c
@@ -316,8 +316,10 @@ static int i2c_amd_probe(struct platform_device *pdev)
amd_mp2_pm_runtime_put(mp2_dev);
- if (ret < 0)
+ if (ret < 0) {
dev_err(&pdev->dev, "i2c add adapter failed = %d\n", ret);
+ amd_mp2_unregister_cb(&i2c_dev->common);
+ }
return ret;
}
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index ad65450aed91..3255a1e53e27 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -870,9 +870,6 @@ static int i2c_imx_reg_slave(struct i2c_client *client)
if (i2c_imx->slave)
return -EBUSY;
- i2c_imx->slave = client;
- i2c_imx->last_slave_event = I2C_SLAVE_STOP;
-
/* Resume */
ret = pm_runtime_resume_and_get(i2c_imx->adapter.dev.parent);
if (ret < 0) {
@@ -880,6 +877,11 @@ static int i2c_imx_reg_slave(struct i2c_client *client)
return ret;
}
+ scoped_guard(spinlock_irqsave, &i2c_imx->slave_lock) {
+ i2c_imx->slave = client;
+ i2c_imx->last_slave_event = I2C_SLAVE_STOP;
+ }
+
i2c_imx_slave_init(i2c_imx);
return 0;
@@ -898,6 +900,7 @@ static int i2c_imx_unreg_slave(struct i2c_client *client)
i2c_imx_reset_regs(i2c_imx);
+ hrtimer_cancel(&i2c_imx->slave_timer);
i2c_imx->slave = NULL;
/* Suspend */
diff --git a/drivers/i2c/busses/i2c-jz4780.c b/drivers/i2c/busses/i2c-jz4780.c
index 55035cca0ae5..58f2430816c9 100644
--- a/drivers/i2c/busses/i2c-jz4780.c
+++ b/drivers/i2c/busses/i2c-jz4780.c
@@ -141,6 +141,7 @@ struct jz4780_i2c {
void __iomem *iomem;
int irq;
struct clk *clk;
+ unsigned long clk_rate_khz;
struct i2c_adapter adap;
const struct ingenic_i2c_config *cdata;
@@ -246,7 +247,7 @@ static int jz4780_i2c_set_target(struct jz4780_i2c *i2c, unsigned char address)
static int jz4780_i2c_set_speed(struct jz4780_i2c *i2c)
{
- int dev_clk_khz = clk_get_rate(i2c->clk) / 1000;
+ int dev_clk_khz = i2c->clk_rate_khz;
int cnt_high = 0; /* HIGH period count of the SCL clock */
int cnt_low = 0; /* LOW period count of the SCL clock */
int cnt_period = 0; /* period count of the SCL clock */
@@ -800,6 +801,8 @@ static int jz4780_i2c_probe(struct platform_device *pdev)
if (ret)
return ret;
+ i2c->clk_rate_khz = clk_get_rate(i2c->clk) / 1000;
+
ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
&clk_freq);
if (ret) {
diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c
index 611733c02b7c..a340b805b82b 100644
--- a/drivers/iommu/iommu-sva.c
+++ b/drivers/iommu/iommu-sva.c
@@ -62,6 +62,9 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
struct iommu_sva *handle;
int ret;
+ if (IS_ENABLED(CONFIG_X86))
+ return ERR_PTR(-EOPNOTSUPP);
+
/* Allocate mm->pasid if necessary. */
ret = iommu_sva_alloc_pasid(mm, dev);
if (ret)
@@ -71,9 +74,6 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
if (!handle)
return ERR_PTR(-ENOMEM);
- if (IS_ENABLED(CONFIG_X86))
- return ERR_PTR(-EOPNOTSUPP);
-
mutex_lock(&iommu_sva_lock);
/* Search for an existing domain. */
domain = iommu_get_domain_for_dev_pasid(dev, mm->pasid,
diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c
index 03cbacd77a80..2b287c1f8eda 100644
--- a/drivers/media/i2c/imx219.c
+++ b/drivers/media/i2c/imx219.c
@@ -18,6 +18,7 @@
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
+#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
@@ -70,21 +71,10 @@
#define IMX219_EXPOSURE_MAX 65535
/* V_TIMING internal */
-#define IMX219_REG_VTS CCI_REG16(0x0160)
-#define IMX219_VTS_15FPS 0x0dc6
-#define IMX219_VTS_30FPS_1080P 0x06e3
-#define IMX219_VTS_30FPS_BINNED 0x06e3
-#define IMX219_VTS_30FPS_640x480 0x06e3
-#define IMX219_VTS_MAX 0xffff
-
+#define IMX219_REG_FRM_LENGTH_A CCI_REG16(0x0160)
+#define IMX219_FLL_MAX 0xfffe
#define IMX219_VBLANK_MIN 32
-/*Frame Length Line*/
-#define IMX219_FLL_MIN 0x08a6
-#define IMX219_FLL_MAX 0xffff
-#define IMX219_FLL_STEP 1
-#define IMX219_FLL_DEFAULT 0x0c98
-
/* HBLANK control - read only */
#define IMX219_PPL_DEFAULT 3448
@@ -171,11 +161,8 @@ struct imx219_mode {
/* Frame height */
unsigned int height;
- /* Analog crop rectangle. */
- struct v4l2_rect crop;
-
/* V-timing */
- unsigned int vts_def;
+ unsigned int fll_def;
/* Default register values */
struct imx219_reg_list reg_list;
@@ -375,13 +362,7 @@ static const struct imx219_mode supported_modes[] = {
/* 8MPix 15fps mode */
.width = 3280,
.height = 2464,
- .crop = {
- .left = IMX219_PIXEL_ARRAY_LEFT,
- .top = IMX219_PIXEL_ARRAY_TOP,
- .width = 3280,
- .height = 2464
- },
- .vts_def = IMX219_VTS_15FPS,
+ .fll_def = 3526,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_3280x2464_regs),
.regs = mode_3280x2464_regs,
@@ -392,13 +373,7 @@ static const struct imx219_mode supported_modes[] = {
/* 1080P 30fps cropped */
.width = 1920,
.height = 1080,
- .crop = {
- .left = 688,
- .top = 700,
- .width = 1920,
- .height = 1080
- },
- .vts_def = IMX219_VTS_30FPS_1080P,
+ .fll_def = 1763,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_1920_1080_regs),
.regs = mode_1920_1080_regs,
@@ -409,13 +384,7 @@ static const struct imx219_mode supported_modes[] = {
/* 2x2 binned 30fps mode */
.width = 1640,
.height = 1232,
- .crop = {
- .left = IMX219_PIXEL_ARRAY_LEFT,
- .top = IMX219_PIXEL_ARRAY_TOP,
- .width = 3280,
- .height = 2464
- },
- .vts_def = IMX219_VTS_30FPS_BINNED,
+ .fll_def = 1763,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_1640_1232_regs),
.regs = mode_1640_1232_regs,
@@ -426,13 +395,7 @@ static const struct imx219_mode supported_modes[] = {
/* 640x480 30fps mode */
.width = 640,
.height = 480,
- .crop = {
- .left = 1008,
- .top = 760,
- .width = 1280,
- .height = 960
- },
- .vts_def = IMX219_VTS_30FPS_640x480,
+ .fll_def = 1763,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_640_480_regs),
.regs = mode_640_480_regs,
@@ -495,18 +458,27 @@ static u32 imx219_get_format_code(struct imx219 *imx219, u32 code)
return imx219_mbus_formats[i];
}
+/* -----------------------------------------------------------------------------
+ * Controls
+ */
+
static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
{
struct imx219 *imx219 =
container_of(ctrl->handler, struct imx219, ctrl_handler);
struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
+ const struct v4l2_mbus_framefmt *format;
+ struct v4l2_subdev_state *state;
int ret = 0;
+ state = v4l2_subdev_get_locked_active_state(&imx219->sd);
+ format = v4l2_subdev_get_pad_format(&imx219->sd, state, 0);
+
if (ctrl->id == V4L2_CID_VBLANK) {
int exposure_max, exposure_def;
/* Update max exposure while meeting expected vblanking */
- exposure_max = imx219->mode->height + ctrl->val - 4;
+ exposure_max = format->height + ctrl->val - 4;
exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
exposure_max : IMX219_EXPOSURE_DEFAULT;
__v4l2_ctrl_modify_range(imx219->exposure,
@@ -545,8 +517,8 @@ static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
imx219->hflip->val | imx219->vflip->val << 1, &ret);
break;
case V4L2_CID_VBLANK:
- cci_write(imx219->regmap, IMX219_REG_VTS,
- imx219->mode->height + ctrl->val, &ret);
+ cci_write(imx219->regmap, IMX219_REG_FRM_LENGTH_A,
+ format->height + ctrl->val, &ret);
break;
case V4L2_CID_TEST_PATTERN_RED:
cci_write(imx219->regmap, IMX219_REG_TESTP_RED,
@@ -581,130 +553,135 @@ static const struct v4l2_ctrl_ops imx219_ctrl_ops = {
.s_ctrl = imx219_set_ctrl,
};
-static void imx219_update_pad_format(struct imx219 *imx219,
- const struct imx219_mode *mode,
- struct v4l2_mbus_framefmt *fmt, u32 code)
+static unsigned long imx219_get_pixel_rate(struct imx219 *imx219)
{
- /* Bayer order varies with flips */
- fmt->code = imx219_get_format_code(imx219, code);
- fmt->width = mode->width;
- fmt->height = mode->height;
- fmt->field = V4L2_FIELD_NONE;
- fmt->colorspace = V4L2_COLORSPACE_RAW;
- fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
- fmt->xfer_func = V4L2_XFER_FUNC_NONE;
+ return (imx219->lanes == 2) ? IMX219_PIXEL_RATE : IMX219_PIXEL_RATE_4LANE;
}
-static int imx219_init_cfg(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *state)
+/* Initialize control handlers */
+static int imx219_init_controls(struct imx219 *imx219)
{
- struct imx219 *imx219 = to_imx219(sd);
- struct v4l2_mbus_framefmt *format;
- struct v4l2_rect *crop;
-
- /* Initialize the format. */
- format = v4l2_subdev_get_pad_format(sd, state, 0);
- imx219_update_pad_format(imx219, &supported_modes[0], format,
- MEDIA_BUS_FMT_SRGGB10_1X10);
-
- /* Initialize the crop rectangle. */
- crop = v4l2_subdev_get_pad_crop(sd, state, 0);
- crop->top = IMX219_PIXEL_ARRAY_TOP;
- crop->left = IMX219_PIXEL_ARRAY_LEFT;
- crop->width = IMX219_PIXEL_ARRAY_WIDTH;
- crop->height = IMX219_PIXEL_ARRAY_HEIGHT;
+ struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
+ const struct imx219_mode *mode = &supported_modes[0];
+ struct v4l2_ctrl_handler *ctrl_hdlr;
+ struct v4l2_fwnode_device_properties props;
+ int exposure_max, exposure_def, hblank;
+ int i, ret;
- return 0;
-}
+ ctrl_hdlr = &imx219->ctrl_handler;
+ ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12);
+ if (ret)
+ return ret;
-static int imx219_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state,
- struct v4l2_subdev_mbus_code_enum *code)
-{
- struct imx219 *imx219 = to_imx219(sd);
+ /* By default, PIXEL_RATE is read only */
+ imx219->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+ V4L2_CID_PIXEL_RATE,
+ imx219_get_pixel_rate(imx219),
+ imx219_get_pixel_rate(imx219), 1,
+ imx219_get_pixel_rate(imx219));
- if (code->index >= (ARRAY_SIZE(imx219_mbus_formats) / 4))
- return -EINVAL;
+ imx219->link_freq =
+ v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx219_ctrl_ops,
+ V4L2_CID_LINK_FREQ,
+ ARRAY_SIZE(imx219_link_freq_menu) - 1, 0,
+ (imx219->lanes == 2) ? imx219_link_freq_menu :
+ imx219_link_freq_4lane_menu);
+ if (imx219->link_freq)
+ imx219->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
- code->code = imx219_get_format_code(imx219, imx219_mbus_formats[code->index * 4]);
+ /* Initial vblank/hblank/exposure parameters based on current mode */
+ imx219->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+ V4L2_CID_VBLANK, IMX219_VBLANK_MIN,
+ IMX219_FLL_MAX - mode->height, 1,
+ mode->fll_def - mode->height);
+ hblank = IMX219_PPL_DEFAULT - mode->width;
+ imx219->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+ V4L2_CID_HBLANK, hblank, hblank,
+ 1, hblank);
+ if (imx219->hblank)
+ imx219->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+ exposure_max = mode->fll_def - 4;
+ exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
+ exposure_max : IMX219_EXPOSURE_DEFAULT;
+ imx219->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+ V4L2_CID_EXPOSURE,
+ IMX219_EXPOSURE_MIN, exposure_max,
+ IMX219_EXPOSURE_STEP,
+ exposure_def);
- return 0;
-}
+ v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
+ IMX219_ANA_GAIN_MIN, IMX219_ANA_GAIN_MAX,
+ IMX219_ANA_GAIN_STEP, IMX219_ANA_GAIN_DEFAULT);
-static int imx219_enum_frame_size(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state,
- struct v4l2_subdev_frame_size_enum *fse)
-{
- struct imx219 *imx219 = to_imx219(sd);
- u32 code;
+ v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
+ IMX219_DGTL_GAIN_MIN, IMX219_DGTL_GAIN_MAX,
+ IMX219_DGTL_GAIN_STEP, IMX219_DGTL_GAIN_DEFAULT);
- if (fse->index >= ARRAY_SIZE(supported_modes))
- return -EINVAL;
+ imx219->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+ V4L2_CID_HFLIP, 0, 1, 1, 0);
+ if (imx219->hflip)
+ imx219->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
- code = imx219_get_format_code(imx219, fse->code);
- if (fse->code != code)
- return -EINVAL;
+ imx219->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+ V4L2_CID_VFLIP, 0, 1, 1, 0);
+ if (imx219->vflip)
+ imx219->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
- fse->min_width = supported_modes[fse->index].width;
- fse->max_width = fse->min_width;
- fse->min_height = supported_modes[fse->index].height;
- fse->max_height = fse->min_height;
+ v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx219_ctrl_ops,
+ V4L2_CID_TEST_PATTERN,
+ ARRAY_SIZE(imx219_test_pattern_menu) - 1,
+ 0, 0, imx219_test_pattern_menu);
+ for (i = 0; i < 4; i++) {
+ /*
+ * The assumption is that
+ * V4L2_CID_TEST_PATTERN_GREENR == V4L2_CID_TEST_PATTERN_RED + 1
+ * V4L2_CID_TEST_PATTERN_BLUE == V4L2_CID_TEST_PATTERN_RED + 2
+ * V4L2_CID_TEST_PATTERN_GREENB == V4L2_CID_TEST_PATTERN_RED + 3
+ */
+ v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+ V4L2_CID_TEST_PATTERN_RED + i,
+ IMX219_TESTP_COLOUR_MIN,
+ IMX219_TESTP_COLOUR_MAX,
+ IMX219_TESTP_COLOUR_STEP,
+ IMX219_TESTP_COLOUR_MAX);
+ /* The "Solid color" pattern is white by default */
+ }
- return 0;
-}
+ if (ctrl_hdlr->error) {
+ ret = ctrl_hdlr->error;
+ dev_err(&client->dev, "%s control init failed (%d)\n",
+ __func__, ret);
+ goto error;
+ }
-static int imx219_set_pad_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state,
- struct v4l2_subdev_format *fmt)
-{
- struct imx219 *imx219 = to_imx219(sd);
- const struct imx219_mode *mode;
- int exposure_max, exposure_def, hblank;
- struct v4l2_mbus_framefmt *format;
- struct v4l2_rect *crop;
+ ret = v4l2_fwnode_device_parse(&client->dev, &props);
+ if (ret)
+ goto error;
- mode = v4l2_find_nearest_size(supported_modes,
- ARRAY_SIZE(supported_modes),
- width, height,
- fmt->format.width, fmt->format.height);
+ ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx219_ctrl_ops,
+ &props);
+ if (ret)
+ goto error;
- imx219_update_pad_format(imx219, mode, &fmt->format, fmt->format.code);
+ imx219->sd.ctrl_handler = ctrl_hdlr;
- format = v4l2_subdev_get_pad_format(sd, sd_state, 0);
- crop = v4l2_subdev_get_pad_crop(sd, sd_state, 0);
+ return 0;
- *format = fmt->format;
- *crop = mode->crop;
+error:
+ v4l2_ctrl_handler_free(ctrl_hdlr);
- if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
- imx219->mode = mode;
- /* Update limits and set FPS to default */
- __v4l2_ctrl_modify_range(imx219->vblank, IMX219_VBLANK_MIN,
- IMX219_VTS_MAX - mode->height, 1,
- mode->vts_def - mode->height);
- __v4l2_ctrl_s_ctrl(imx219->vblank,
- mode->vts_def - mode->height);
- /* Update max exposure while meeting expected vblanking */
- exposure_max = mode->vts_def - 4;
- exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
- exposure_max : IMX219_EXPOSURE_DEFAULT;
- __v4l2_ctrl_modify_range(imx219->exposure,
- imx219->exposure->minimum,
- exposure_max, imx219->exposure->step,
- exposure_def);
- /*
- * Currently PPL is fixed to IMX219_PPL_DEFAULT, so hblank
- * depends on mode->width only, and is not changeble in any
- * way other than changing the mode.
- */
- hblank = IMX219_PPL_DEFAULT - mode->width;
- __v4l2_ctrl_modify_range(imx219->hblank, hblank, hblank, 1,
- hblank);
- }
+ return ret;
+}
- return 0;
+static void imx219_free_controls(struct imx219 *imx219)
+{
+ v4l2_ctrl_handler_free(imx219->sd.ctrl_handler);
}
+/* -----------------------------------------------------------------------------
+ * Subdev operations
+ */
+
static int imx219_set_framefmt(struct imx219 *imx219,
const struct v4l2_mbus_framefmt *format)
{
@@ -753,37 +730,6 @@ static int imx219_set_binning(struct imx219 *imx219,
return -EINVAL;
}
-static int imx219_get_selection(struct v4l2_subdev *sd,
- struct v4l2_subdev_state *sd_state,
- struct v4l2_subdev_selection *sel)
-{
- switch (sel->target) {
- case V4L2_SEL_TGT_CROP: {
- sel->r = *v4l2_subdev_get_pad_crop(sd, sd_state, 0);
- return 0;
- }
-
- case V4L2_SEL_TGT_NATIVE_SIZE:
- sel->r.top = 0;
- sel->r.left = 0;
- sel->r.width = IMX219_NATIVE_WIDTH;
- sel->r.height = IMX219_NATIVE_HEIGHT;
-
- return 0;
-
- case V4L2_SEL_TGT_CROP_DEFAULT:
- case V4L2_SEL_TGT_CROP_BOUNDS:
- sel->r.top = IMX219_PIXEL_ARRAY_TOP;
- sel->r.left = IMX219_PIXEL_ARRAY_LEFT;
- sel->r.width = IMX219_PIXEL_ARRAY_WIDTH;
- sel->r.height = IMX219_PIXEL_ARRAY_HEIGHT;
-
- return 0;
- }
-
- return -EINVAL;
-}
-
static int imx219_configure_lanes(struct imx219 *imx219)
{
return cci_write(imx219->regmap, IMX219_REG_CSI_LANE_MODE,
@@ -912,13 +858,208 @@ static int imx219_set_stream(struct v4l2_subdev *sd, int enable)
}
/* Power/clock management functions */
-static int imx219_power_on(struct device *dev)
+static void imx219_update_pad_format(struct imx219 *imx219,
+ const struct imx219_mode *mode,
+ struct v4l2_mbus_framefmt *fmt, u32 code)
{
- struct v4l2_subdev *sd = dev_get_drvdata(dev);
- struct imx219 *imx219 = to_imx219(sd);
- int ret;
+ /* Bayer order varies with flips */
+ fmt->code = imx219_get_format_code(imx219, code);
+ fmt->width = mode->width;
+ fmt->height = mode->height;
+ fmt->field = V4L2_FIELD_NONE;
+ fmt->colorspace = V4L2_COLORSPACE_RAW;
+ fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
+ fmt->xfer_func = V4L2_XFER_FUNC_NONE;
+}
- ret = regulator_bulk_enable(IMX219_NUM_SUPPLIES,
+static int imx219_init_cfg(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state)
+{
+ struct imx219 *imx219 = to_imx219(sd);
+ struct v4l2_mbus_framefmt *format;
+ struct v4l2_rect *crop;
+
+ /* Initialize the format. */
+ format = v4l2_subdev_get_pad_format(sd, state, 0);
+ imx219_update_pad_format(imx219, &supported_modes[0], format,
+ MEDIA_BUS_FMT_SRGGB10_1X10);
+
+ /* Initialize the crop rectangle. */
+ crop = v4l2_subdev_get_pad_crop(sd, state, 0);
+ crop->top = IMX219_PIXEL_ARRAY_TOP;
+ crop->left = IMX219_PIXEL_ARRAY_LEFT;
+ crop->width = IMX219_PIXEL_ARRAY_WIDTH;
+ crop->height = IMX219_PIXEL_ARRAY_HEIGHT;
+
+ return 0;
+}
+
+static int imx219_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ struct imx219 *imx219 = to_imx219(sd);
+
+ if (code->index >= (ARRAY_SIZE(imx219_mbus_formats) / 4))
+ return -EINVAL;
+
+ code->code = imx219_get_format_code(imx219, imx219_mbus_formats[code->index * 4]);
+
+ return 0;
+}
+
+static int imx219_enum_frame_size(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ struct imx219 *imx219 = to_imx219(sd);
+ u32 code;
+
+ if (fse->index >= ARRAY_SIZE(supported_modes))
+ return -EINVAL;
+
+ code = imx219_get_format_code(imx219, fse->code);
+ if (fse->code != code)
+ return -EINVAL;
+
+ fse->min_width = supported_modes[fse->index].width;
+ fse->max_width = fse->min_width;
+ fse->min_height = supported_modes[fse->index].height;
+ fse->max_height = fse->min_height;
+
+ return 0;
+}
+
+static int imx219_set_pad_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *fmt)
+{
+ struct imx219 *imx219 = to_imx219(sd);
+ const struct imx219_mode *mode;
+ int exposure_max, exposure_def, hblank;
+ struct v4l2_mbus_framefmt *format;
+ struct v4l2_rect *crop;
+ unsigned int bin_h, bin_v;
+
+ mode = v4l2_find_nearest_size(supported_modes,
+ ARRAY_SIZE(supported_modes),
+ width, height,
+ fmt->format.width, fmt->format.height);
+
+ imx219_update_pad_format(imx219, mode, &fmt->format, fmt->format.code);
+
+ format = v4l2_subdev_get_pad_format(sd, sd_state, 0);
+ *format = fmt->format;
+
+ /*
+ * Use binning to maximize the crop rectangle size, and centre it in the
+ * sensor.
+ */
+ bin_h = min(IMX219_PIXEL_ARRAY_WIDTH / format->width, 2U);
+ bin_v = min(IMX219_PIXEL_ARRAY_HEIGHT / format->height, 2U);
+
+ crop = v4l2_subdev_get_pad_crop(sd, sd_state, 0);
+ crop->width = format->width * bin_h;
+ crop->height = format->height * bin_v;
+ crop->left = (IMX219_NATIVE_WIDTH - crop->width) / 2;
+ crop->top = (IMX219_NATIVE_HEIGHT - crop->height) / 2;
+
+ if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+ imx219->mode = mode;
+ /* Update limits and set FPS to default */
+ __v4l2_ctrl_modify_range(imx219->vblank, IMX219_VBLANK_MIN,
+ IMX219_FLL_MAX - mode->height, 1,
+ mode->fll_def - mode->height);
+ __v4l2_ctrl_s_ctrl(imx219->vblank,
+ mode->fll_def - mode->height);
+ /* Update max exposure while meeting expected vblanking */
+ exposure_max = mode->fll_def - 4;
+ exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
+ exposure_max : IMX219_EXPOSURE_DEFAULT;
+ __v4l2_ctrl_modify_range(imx219->exposure,
+ imx219->exposure->minimum,
+ exposure_max, imx219->exposure->step,
+ exposure_def);
+ /*
+ * Currently PPL is fixed to IMX219_PPL_DEFAULT, so hblank
+ * depends on mode->width only, and is not changeble in any
+ * way other than changing the mode.
+ */
+ hblank = IMX219_PPL_DEFAULT - mode->width;
+ __v4l2_ctrl_modify_range(imx219->hblank, hblank, hblank, 1,
+ hblank);
+ }
+
+ return 0;
+}
+
+static int imx219_get_selection(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_selection *sel)
+{
+ switch (sel->target) {
+ case V4L2_SEL_TGT_CROP: {
+ sel->r = *v4l2_subdev_get_pad_crop(sd, sd_state, 0);
+ return 0;
+ }
+
+ case V4L2_SEL_TGT_NATIVE_SIZE:
+ sel->r.top = 0;
+ sel->r.left = 0;
+ sel->r.width = IMX219_NATIVE_WIDTH;
+ sel->r.height = IMX219_NATIVE_HEIGHT;
+
+ return 0;
+
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+ case V4L2_SEL_TGT_CROP_BOUNDS:
+ sel->r.top = IMX219_PIXEL_ARRAY_TOP;
+ sel->r.left = IMX219_PIXEL_ARRAY_LEFT;
+ sel->r.width = IMX219_PIXEL_ARRAY_WIDTH;
+ sel->r.height = IMX219_PIXEL_ARRAY_HEIGHT;
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static const struct v4l2_subdev_core_ops imx219_core_ops = {
+ .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
+ .unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
+static const struct v4l2_subdev_video_ops imx219_video_ops = {
+ .s_stream = imx219_set_stream,
+};
+
+static const struct v4l2_subdev_pad_ops imx219_pad_ops = {
+ .init_cfg = imx219_init_cfg,
+ .enum_mbus_code = imx219_enum_mbus_code,
+ .get_fmt = v4l2_subdev_get_fmt,
+ .set_fmt = imx219_set_pad_format,
+ .get_selection = imx219_get_selection,
+ .enum_frame_size = imx219_enum_frame_size,
+};
+
+static const struct v4l2_subdev_ops imx219_subdev_ops = {
+ .core = &imx219_core_ops,
+ .video = &imx219_video_ops,
+ .pad = &imx219_pad_ops,
+};
+
+
+/* -----------------------------------------------------------------------------
+ * Power management
+ */
+
+static int imx219_power_on(struct device *dev)
+{
+ struct v4l2_subdev *sd = dev_get_drvdata(dev);
+ struct imx219 *imx219 = to_imx219(sd);
+ int ret;
+
+ ret = regulator_bulk_enable(IMX219_NUM_SUPPLIES,
imx219->supplies);
if (ret) {
dev_err(dev, "%s: failed to enable regulators\n",
@@ -992,6 +1133,10 @@ static int __maybe_unused imx219_resume(struct device *dev)
return ret;
}
+/* -----------------------------------------------------------------------------
+ * Probe & remove
+ */
+
static int imx219_get_regulators(struct imx219 *imx219)
{
struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
@@ -1028,156 +1173,6 @@ static int imx219_identify_module(struct imx219 *imx219)
return 0;
}
-static const struct v4l2_subdev_core_ops imx219_core_ops = {
- .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
- .unsubscribe_event = v4l2_event_subdev_unsubscribe,
-};
-
-static const struct v4l2_subdev_video_ops imx219_video_ops = {
- .s_stream = imx219_set_stream,
-};
-
-static const struct v4l2_subdev_pad_ops imx219_pad_ops = {
- .init_cfg = imx219_init_cfg,
- .enum_mbus_code = imx219_enum_mbus_code,
- .get_fmt = v4l2_subdev_get_fmt,
- .set_fmt = imx219_set_pad_format,
- .get_selection = imx219_get_selection,
- .enum_frame_size = imx219_enum_frame_size,
-};
-
-static const struct v4l2_subdev_ops imx219_subdev_ops = {
- .core = &imx219_core_ops,
- .video = &imx219_video_ops,
- .pad = &imx219_pad_ops,
-};
-
-
-static unsigned long imx219_get_pixel_rate(struct imx219 *imx219)
-{
- return (imx219->lanes == 2) ? IMX219_PIXEL_RATE : IMX219_PIXEL_RATE_4LANE;
-}
-
-/* Initialize control handlers */
-static int imx219_init_controls(struct imx219 *imx219)
-{
- struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
- struct v4l2_ctrl_handler *ctrl_hdlr;
- unsigned int height = imx219->mode->height;
- struct v4l2_fwnode_device_properties props;
- int exposure_max, exposure_def, hblank;
- int i, ret;
-
- ctrl_hdlr = &imx219->ctrl_handler;
- ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12);
- if (ret)
- return ret;
-
- /* By default, PIXEL_RATE is read only */
- imx219->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
- V4L2_CID_PIXEL_RATE,
- imx219_get_pixel_rate(imx219),
- imx219_get_pixel_rate(imx219), 1,
- imx219_get_pixel_rate(imx219));
-
- imx219->link_freq =
- v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx219_ctrl_ops,
- V4L2_CID_LINK_FREQ,
- ARRAY_SIZE(imx219_link_freq_menu) - 1, 0,
- (imx219->lanes == 2) ? imx219_link_freq_menu :
- imx219_link_freq_4lane_menu);
- if (imx219->link_freq)
- imx219->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-
- /* Initial vblank/hblank/exposure parameters based on current mode */
- imx219->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
- V4L2_CID_VBLANK, IMX219_VBLANK_MIN,
- IMX219_VTS_MAX - height, 1,
- imx219->mode->vts_def - height);
- hblank = IMX219_PPL_DEFAULT - imx219->mode->width;
- imx219->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
- V4L2_CID_HBLANK, hblank, hblank,
- 1, hblank);
- if (imx219->hblank)
- imx219->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
- exposure_max = imx219->mode->vts_def - 4;
- exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
- exposure_max : IMX219_EXPOSURE_DEFAULT;
- imx219->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
- V4L2_CID_EXPOSURE,
- IMX219_EXPOSURE_MIN, exposure_max,
- IMX219_EXPOSURE_STEP,
- exposure_def);
-
- v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
- IMX219_ANA_GAIN_MIN, IMX219_ANA_GAIN_MAX,
- IMX219_ANA_GAIN_STEP, IMX219_ANA_GAIN_DEFAULT);
-
- v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
- IMX219_DGTL_GAIN_MIN, IMX219_DGTL_GAIN_MAX,
- IMX219_DGTL_GAIN_STEP, IMX219_DGTL_GAIN_DEFAULT);
-
- imx219->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
- V4L2_CID_HFLIP, 0, 1, 1, 0);
- if (imx219->hflip)
- imx219->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
-
- imx219->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
- V4L2_CID_VFLIP, 0, 1, 1, 0);
- if (imx219->vflip)
- imx219->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
-
- v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx219_ctrl_ops,
- V4L2_CID_TEST_PATTERN,
- ARRAY_SIZE(imx219_test_pattern_menu) - 1,
- 0, 0, imx219_test_pattern_menu);
- for (i = 0; i < 4; i++) {
- /*
- * The assumption is that
- * V4L2_CID_TEST_PATTERN_GREENR == V4L2_CID_TEST_PATTERN_RED + 1
- * V4L2_CID_TEST_PATTERN_BLUE == V4L2_CID_TEST_PATTERN_RED + 2
- * V4L2_CID_TEST_PATTERN_GREENB == V4L2_CID_TEST_PATTERN_RED + 3
- */
- v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
- V4L2_CID_TEST_PATTERN_RED + i,
- IMX219_TESTP_COLOUR_MIN,
- IMX219_TESTP_COLOUR_MAX,
- IMX219_TESTP_COLOUR_STEP,
- IMX219_TESTP_COLOUR_MAX);
- /* The "Solid color" pattern is white by default */
- }
-
- if (ctrl_hdlr->error) {
- ret = ctrl_hdlr->error;
- dev_err(&client->dev, "%s control init failed (%d)\n",
- __func__, ret);
- goto error;
- }
-
- ret = v4l2_fwnode_device_parse(&client->dev, &props);
- if (ret)
- goto error;
-
- ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx219_ctrl_ops,
- &props);
- if (ret)
- goto error;
-
- imx219->sd.ctrl_handler = ctrl_hdlr;
-
- return 0;
-
-error:
- v4l2_ctrl_handler_free(ctrl_hdlr);
-
- return ret;
-}
-
-static void imx219_free_controls(struct imx219 *imx219)
-{
- v4l2_ctrl_handler_free(imx219->sd.ctrl_handler);
-}
-
static int imx219_check_hwcfg(struct device *dev, struct imx219 *imx219)
{
struct fwnode_handle *endpoint;
@@ -1293,7 +1288,8 @@ static int imx219_probe(struct i2c_client *client)
/* Set default mode to max resolution */
imx219->mode = &supported_modes[0];
- /* sensor doesn't enter LP-11 state upon power up until and unless
+ /*
+ * Sensor doesn't enter LP-11 state upon power up until and unless
* streaming is started, so upon power up switch the modes to:
* streaming -> standby
*/
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index cf2923dea84b..36df65475dad 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -798,7 +798,7 @@ v4l2_async_connection_unique(struct v4l2_subdev *sd)
}
EXPORT_SYMBOL_GPL(v4l2_async_connection_unique);
-int v4l2_async_register_subdev(struct v4l2_subdev *sd)
+int __v4l2_async_register_subdev(struct v4l2_subdev *sd, struct module *module)
{
struct v4l2_async_notifier *subdev_notifier;
struct v4l2_async_notifier *notifier;
@@ -822,6 +822,8 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
return -EINVAL;
}
+ sd->owner = module;
+
mutex_lock(&list_lock);
list_for_each_entry(notifier, ¬ifier_list, notifier_entry) {
@@ -869,9 +871,11 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
err_unlock:
mutex_unlock(&list_lock);
+ sd->owner = NULL;
+
return ret;
}
-EXPORT_SYMBOL(v4l2_async_register_subdev);
+EXPORT_SYMBOL(__v4l2_async_register_subdev);
void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
{
diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
index 7f181fbbb140..519eaad0af5f 100644
--- a/drivers/media/v4l2-core/v4l2-fwnode.c
+++ b/drivers/media/v4l2-core/v4l2-fwnode.c
@@ -1203,7 +1203,7 @@ v4l2_async_nf_parse_fwnode_sensor(struct device *dev,
return 0;
}
-int v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd)
+int __v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd, struct module *module)
{
struct v4l2_async_notifier *notifier;
int ret;
@@ -1229,7 +1229,7 @@ int v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd)
if (ret < 0)
goto out_cleanup;
- ret = v4l2_async_register_subdev(sd);
+ ret = __v4l2_async_register_subdev(sd, module);
if (ret < 0)
goto out_unregister;
@@ -1247,7 +1247,7 @@ int v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd)
return ret;
}
-EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor);
+EXPORT_SYMBOL_GPL(__v4l2_async_register_subdev_sensor);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>");
diff --git a/drivers/net/can/c_can/c_can_main.c b/drivers/net/can/c_can/c_can_main.c
index cc371d0c9f3c..2ea5224ebfcb 100644
--- a/drivers/net/can/c_can/c_can_main.c
+++ b/drivers/net/can/c_can/c_can_main.c
@@ -597,20 +597,20 @@ static int c_can_chip_config(struct net_device *dev)
return err;
/* enable automatic retransmission */
- priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR);
+ priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR | CONTROL_INIT);
if ((priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) &&
(priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)) {
/* loopback + silent mode : useful for hot self-test */
- priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST);
+ priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST | CONTROL_INIT);
priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK | TEST_SILENT);
} else if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
/* loopback mode : useful for self-test function */
- priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST);
+ priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST | CONTROL_INIT);
priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK);
} else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
/* silent mode : bus-monitoring mode */
- priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST);
+ priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST | CONTROL_INIT);
priv->write_reg(priv, C_CAN_TEST_REG, TEST_SILENT);
}
diff --git a/drivers/net/can/ctucanfd/ctucanfd_base.c b/drivers/net/can/ctucanfd/ctucanfd_base.c
index 0d40564febee..31fc0b8573bb 100644
--- a/drivers/net/can/ctucanfd/ctucanfd_base.c
+++ b/drivers/net/can/ctucanfd/ctucanfd_base.c
@@ -340,8 +340,8 @@ static void ctucan_set_mode(struct ctucan_priv *priv, const struct can_ctrlmode
(mode_reg & ~REG_MODE_FDE);
mode_reg = (mode->flags & CAN_CTRLMODE_PRESUME_ACK) ?
- (mode_reg | REG_MODE_ACF) :
- (mode_reg & ~REG_MODE_ACF);
+ (mode_reg | REG_MODE_STM) :
+ (mode_reg & ~REG_MODE_STM);
mode_reg = (mode->flags & CAN_CTRLMODE_FD_NON_ISO) ?
(mode_reg | REG_MODE_NISOFD) :
@@ -868,7 +868,7 @@ static void ctucan_err_interrupt(struct net_device *ndev, u32 isr)
break;
case CAN_STATE_ERROR_ACTIVE:
if (skb) {
- cf->can_id |= CAN_ERR_CNT;
+ cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
cf->data[1] = CAN_ERR_CRTL_ACTIVE;
cf->data[6] = bec.txerr;
cf->data[7] = bec.rxerr;
@@ -1135,8 +1135,12 @@ static irqreturn_t ctucan_interrupt(int irq, void *dev_id)
/* Error interrupts */
if (FIELD_GET(REG_INT_STAT_EWLI, isr) ||
FIELD_GET(REG_INT_STAT_FCSI, isr) ||
- FIELD_GET(REG_INT_STAT_ALI, isr)) {
- icr = isr & (REG_INT_STAT_EWLI | REG_INT_STAT_FCSI | REG_INT_STAT_ALI);
+ FIELD_GET(REG_INT_STAT_ALI, isr) ||
+ FIELD_GET(REG_INT_STAT_BEI, isr)) {
+ icr = isr & (REG_INT_STAT_EWLI |
+ REG_INT_STAT_FCSI |
+ REG_INT_STAT_ALI |
+ REG_INT_STAT_BEI);
ctucan_netdev_dbg(ndev, "some ERR interrupt: clearing 0x%08x\n", icr);
ctucan_write32(priv, CTUCANFD_INT_STAT, icr);
diff --git a/drivers/net/can/ctucanfd/ctucanfd_pci.c b/drivers/net/can/ctucanfd/ctucanfd_pci.c
index 9da09e7dd63a..8cc995649287 100644
--- a/drivers/net/can/ctucanfd/ctucanfd_pci.c
+++ b/drivers/net/can/ctucanfd/ctucanfd_pci.c
@@ -202,7 +202,7 @@ static int ctucan_pci_probe(struct pci_dev *pdev,
pci_set_drvdata(pdev, NULL);
kfree(bdata);
err_pci_iounmap_bar0:
- pci_iounmap(pdev, cra_addr);
+ pci_iounmap(pdev, bar0_base);
err_pci_iounmap_bar1:
pci_iounmap(pdev, addr);
err_release_regions:
@@ -274,6 +274,7 @@ static const struct pci_device_id ctucan_pci_tbl[] = {
CTUCAN_WITH_CTUCAN_ID)},
{},
};
+MODULE_DEVICE_TABLE(pci, ctucan_pci_tbl);
static struct pci_driver ctucan_pci_driver = {
.name = KBUILD_MODNAME,
diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c
index 3ebd4f779b9b..0da615afa04d 100644
--- a/drivers/net/can/dev/skb.c
+++ b/drivers/net/can/dev/skb.c
@@ -202,7 +202,6 @@ static void init_can_skb_reserve(struct sk_buff *skb)
skb_reset_transport_header(skb);
can_skb_reserve(skb);
- can_skb_prv(skb)->skbcnt = 0;
}
struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
@@ -312,7 +311,6 @@ static bool can_skb_headroom_valid(struct net_device *dev, struct sk_buff *skb)
if (skb->ip_summed == CHECKSUM_NONE) {
/* init headroom */
can_skb_prv(skb)->ifindex = dev->ifindex;
- can_skb_prv(skb)->skbcnt = 0;
skb->ip_summed = CHECKSUM_UNNECESSARY;
diff --git a/drivers/net/can/softing/softing_fw.c b/drivers/net/can/softing/softing_fw.c
index 32286f861a19..6776577a0bba 100644
--- a/drivers/net/can/softing/softing_fw.c
+++ b/drivers/net/can/softing/softing_fw.c
@@ -91,12 +91,12 @@ int softing_bootloader_command(struct softing *card, int16_t cmd,
return ret;
}
-static int fw_parse(const uint8_t **pmem, uint16_t *ptype, uint32_t *paddr,
- uint16_t *plen, const uint8_t **pdat)
+static int fw_parse(const u8 **pmem, const u8 *limit, u16 *ptype,
+ u32 *paddr, u16 *plen, const u8 **pdat)
{
uint16_t checksum[2];
- const uint8_t *mem;
- const uint8_t *end;
+ const u8 *mem;
+ const u8 *record_end;
/*
* firmware records are a binary, unaligned stream composed of:
@@ -114,14 +114,21 @@ static int fw_parse(const uint8_t **pmem, uint16_t *ptype, uint32_t *paddr,
* endianness & alignment.
*/
mem = *pmem;
+ /* A record needs an 8-byte prefix and a 2-byte checksum. */
+ if (mem > limit || limit - mem < 10)
+ return -EINVAL;
+
*ptype = le16_to_cpup((void *)&mem[0]);
*paddr = le32_to_cpup((void *)&mem[2]);
*plen = le16_to_cpup((void *)&mem[6]);
+ if (*plen > limit - mem - 10)
+ return -EINVAL;
+
*pdat = &mem[8];
/* verify checksum */
- end = &mem[8 + *plen];
- checksum[0] = le16_to_cpup((void *)end);
- for (checksum[1] = 0; mem < end; ++mem)
+ record_end = &mem[8 + *plen];
+ checksum[0] = le16_to_cpup((void *)record_end);
+ for (checksum[1] = 0; mem < record_end; ++mem)
checksum[1] += *mem;
if (checksum[0] != checksum[1])
return -EINVAL;
@@ -139,6 +146,7 @@ int softing_load_fw(const char *file, struct softing *card,
uint16_t type, len;
uint32_t addr;
uint8_t *buf = NULL, *new_buf;
+ s64 dpram_offset;
int buflen = 0;
int8_t type_end = 0;
@@ -153,7 +161,7 @@ int softing_load_fw(const char *file, struct softing *card,
mem = fw->data;
end = &mem[fw->size];
/* look for header record */
- ret = fw_parse(&mem, &type, &addr, &len, &dat);
+ ret = fw_parse(&mem, end, &type, &addr, &len, &dat);
if (ret < 0)
goto failed;
if (type != 0xffff)
@@ -164,7 +172,7 @@ int softing_load_fw(const char *file, struct softing *card,
}
/* ok, we had a header */
while (mem < end) {
- ret = fw_parse(&mem, &type, &addr, &len, &dat);
+ ret = fw_parse(&mem, end, &type, &addr, &len, &dat);
if (ret < 0)
goto failed;
if (type == 3) {
@@ -179,9 +187,13 @@ int softing_load_fw(const char *file, struct softing *card,
goto failed;
}
- if ((addr + len + offset) > size)
+ dpram_offset = (s64)addr + offset;
+ if (dpram_offset < 0 || dpram_offset > size ||
+ len > size - dpram_offset) {
+ ret = -EINVAL;
goto failed;
- memcpy_toio(&dpram[addr + offset], dat, len);
+ }
+ memcpy_toio(&dpram[dpram_offset], dat, len);
/* be sure to flush caches from IO space */
mb();
if (len > buflen) {
@@ -195,7 +207,7 @@ int softing_load_fw(const char *file, struct softing *card,
buf = new_buf;
}
/* verify record data */
- memcpy_fromio(buf, &dpram[addr + offset], len);
+ memcpy_fromio(buf, &dpram[dpram_offset], len);
if (memcmp(buf, dat, len)) {
/* is not ok */
dev_alert(&card->pdev->dev, "DPRAM readback failed\n");
@@ -237,7 +249,7 @@ int softing_load_app_fw(const char *file, struct softing *card)
mem = fw->data;
end = &mem[fw->size];
/* look for header record */
- ret = fw_parse(&mem, &type, &addr, &len, &dat);
+ ret = fw_parse(&mem, end, &type, &addr, &len, &dat);
if (ret)
goto failed;
ret = -EINVAL;
@@ -253,7 +265,7 @@ int softing_load_app_fw(const char *file, struct softing *card)
}
/* ok, we had a header */
while (mem < end) {
- ret = fw_parse(&mem, &type, &addr, &len, &dat);
+ ret = fw_parse(&mem, end, &type, &addr, &len, &dat);
if (ret)
goto failed;
@@ -279,6 +291,12 @@ int softing_load_app_fw(const char *file, struct softing *card)
/* work in 16bit (target) */
sum &= 0xffff;
+ if (card->pdat->app.offs > card->dpram_size ||
+ len > card->dpram_size - card->pdat->app.offs) {
+ ret = -EINVAL;
+ goto failed;
+ }
+
memcpy_toio(&card->dpram[card->pdat->app.offs], dat, len);
iowrite32(card->pdat->app.offs + card->pdat->app.addr,
&card->dpram[DPRAM_COMMAND + 2]);
diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
index d8c881130e90..4b130c96c9ab 100644
--- a/drivers/net/can/usb/ems_usb.c
+++ b/drivers/net/can/usb/ems_usb.c
@@ -409,6 +409,40 @@ static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg)
netif_rx(skb);
}
+static bool ems_usb_rx_msg_len_valid(struct ems_cpc_msg *msg)
+{
+ size_t len = msg->length;
+ size_t can_len;
+
+ switch (msg->type) {
+ case CPC_MSG_TYPE_CAN_STATE:
+ return len >= sizeof(msg->msg.can_state);
+
+ case CPC_MSG_TYPE_CAN_FRAME:
+ case CPC_MSG_TYPE_EXT_CAN_FRAME:
+ case CPC_MSG_TYPE_RTR_FRAME:
+ case CPC_MSG_TYPE_EXT_RTR_FRAME:
+ if (len < CPC_CAN_MSG_MIN_SIZE)
+ return false;
+
+ if (msg->type == CPC_MSG_TYPE_RTR_FRAME ||
+ msg->type == CPC_MSG_TYPE_EXT_RTR_FRAME)
+ return true;
+
+ can_len = can_cc_dlc2len(msg->msg.can_msg.length & 0xf);
+ return len >= CPC_CAN_MSG_MIN_SIZE + can_len;
+
+ case CPC_MSG_TYPE_CAN_FRAME_ERROR:
+ return len >= sizeof(msg->msg.error);
+
+ case CPC_MSG_TYPE_OVERRUN:
+ return len >= sizeof(msg->msg.overrun);
+
+ default:
+ return true;
+ }
+}
+
/*
* callback for bulk IN urb
*/
@@ -451,6 +485,15 @@ static void ems_usb_read_bulk_callback(struct urb *urb)
}
msg = (struct ems_cpc_msg *)&ibuf[start];
+ if (msg->length >
+ urb->actual_length - start - CPC_MSG_HEADER_LEN) {
+ netdev_err(netdev, "format error\n");
+ break;
+ }
+ if (!ems_usb_rx_msg_len_valid(msg)) {
+ netdev_err(netdev, "format error\n");
+ break;
+ }
switch (msg->type) {
case CPC_MSG_TYPE_CAN_STATE:
diff --git a/drivers/net/can/usb/etas_es58x/es58x_core.c b/drivers/net/can/usb/etas_es58x/es58x_core.c
index e7955c1450d9..1c7f24304c1d 100644
--- a/drivers/net/can/usb/etas_es58x/es58x_core.c
+++ b/drivers/net/can/usb/etas_es58x/es58x_core.c
@@ -1476,7 +1476,6 @@ static void es58x_read_bulk_callback(struct urb *urb)
dev_err_ratelimited(dev,
"Failed resubmitting read bulk urb: %pe\n",
ERR_PTR(ret));
- return;
free_urb:
usb_free_coherent(urb->dev, urb->transfer_buffer_length,
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index bde945d99edd..32770081512b 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -671,7 +671,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
if (hf->flags & GS_CAN_FLAG_FD) {
skb = alloc_canfd_skb(netdev, &cfd);
if (!skb)
- return;
+ goto resubmit_urb;
cfd->can_id = le32_to_cpu(hf->can_id);
cfd->len = data_length;
@@ -684,7 +684,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
} else {
skb = alloc_can_skb(netdev, &cf);
if (!skb)
- return;
+ goto resubmit_urb;
cf->can_id = le32_to_cpu(hf->can_id);
can_frame_set_cc_len(cf, hf->can_dlc, dev->can.ctrlmode);
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
index c7ba768dfe17..426f34728099 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
@@ -1610,6 +1610,7 @@ static int kvaser_usb_hydra_get_busparams(struct kvaser_usb_net_priv *priv,
reinit_completion(&priv->get_busparams_comp);
err = kvaser_usb_send_cmd(dev, cmd, cmd_len);
+ kfree(cmd);
if (err)
return err;
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
index 7b931953dadc..563f5b6e49b2 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
@@ -617,13 +617,22 @@ static int kvaser_usb_leaf_wait_cmd(const struct kvaser_usb *dev, u8 id,
continue;
}
- if (pos + tmp->len > actual_len) {
+ if (tmp->len < CMD_HEADER_LEN ||
+ tmp->len > actual_len - pos) {
dev_err_ratelimited(&dev->intf->dev,
"Format error\n");
break;
}
if (tmp->id == id) {
+ if (tmp->len > sizeof(*cmd)) {
+ dev_err_ratelimited(&dev->intf->dev,
+ "Received command %u too large (%u)\n",
+ tmp->id, tmp->len);
+ err = -EIO;
+ goto end;
+ }
+
memcpy(cmd, tmp, tmp->len);
goto end;
}
@@ -1595,7 +1604,7 @@ static void kvaser_usb_leaf_read_bulk_callback(struct kvaser_usb *dev,
continue;
}
- if (pos + cmd->len > len) {
+ if (cmd->len < CMD_HEADER_LEN || cmd->len > len - pos) {
dev_err_ratelimited(&dev->intf->dev, "Format error\n");
break;
}
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
index 9d162d1004c2..8fd064db1717 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
@@ -470,7 +470,6 @@ static int peak_usb_start(struct peak_usb_device *dev)
netif_device_detach(dev->netdev);
usb_unanchor_urb(urb);
- kfree(buf);
usb_free_urb(urb);
break;
}
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c
index ebefc274b50a..6ebfbc0753d9 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c
@@ -565,6 +565,13 @@ static int pcan_usb_fd_decode_canmsg(struct pcan_usb_fd_if *usb_if,
dev->can.ctrlmode);
}
+ if (!(rx_msg_flags & PUCAN_MSG_RTR) &&
+ le16_to_cpu(rx_msg->size) - offsetof(struct pucan_rx_msg, d) <
+ cfd->len) {
+ kfree_skb(skb);
+ return -EBADMSG;
+ }
+
cfd->can_id = le32_to_cpu(rm->can_id);
if (rx_msg_flags & PUCAN_MSG_EXT_ID)
@@ -713,6 +720,24 @@ static void pcan_usb_fd_decode_ts(struct pcan_usb_fd_if *usb_if,
peak_usb_set_ts_now(&usb_if->time_ref, le32_to_cpu(ts->ts_low));
}
+static size_t pcan_usb_fd_rx_msg_min_size(u16 rx_msg_type)
+{
+ switch (rx_msg_type) {
+ case PUCAN_MSG_CAN_RX:
+ return offsetof(struct pucan_rx_msg, d);
+ case PCAN_UFD_MSG_CALIBRATION:
+ return sizeof(struct pcan_ufd_ts_msg);
+ case PUCAN_MSG_ERROR:
+ return sizeof(struct pucan_error_msg);
+ case PUCAN_MSG_STATUS:
+ return sizeof(struct pucan_status_msg);
+ case PCAN_UFD_MSG_OVERRUN:
+ return sizeof(struct pcan_ufd_ovr_msg);
+ default:
+ return sizeof(struct pucan_msg);
+ }
+}
+
/* callback for bulk IN urb */
static int pcan_usb_fd_decode_buf(struct peak_usb_device *dev, struct urb *urb)
{
@@ -727,6 +752,12 @@ static int pcan_usb_fd_decode_buf(struct peak_usb_device *dev, struct urb *urb)
msg_end = urb->transfer_buffer + urb->actual_length;
for (; msg_ptr < msg_end;) {
u16 rx_msg_type, rx_msg_size;
+ size_t rx_msg_min_size;
+
+ if (msg_end - msg_ptr < sizeof(*rx_msg)) {
+ err = -EBADMSG;
+ break;
+ }
rx_msg = (struct pucan_msg *)msg_ptr;
if (!rx_msg->size) {
@@ -738,13 +769,20 @@ static int pcan_usb_fd_decode_buf(struct peak_usb_device *dev, struct urb *urb)
rx_msg_type = le16_to_cpu(rx_msg->type);
/* check if the record goes out of current packet */
- if (msg_ptr + rx_msg_size > msg_end) {
+ if (rx_msg_size > msg_end - msg_ptr) {
netdev_err(netdev,
"got frag rec: should inc usb rx buf sze\n");
err = -EBADMSG;
break;
}
+ rx_msg_min_size = pcan_usb_fd_rx_msg_min_size(rx_msg_type);
+ if (rx_msg_size < rx_msg_min_size) {
+ netdev_err(netdev, "got short rec\n");
+ err = -EBADMSG;
+ break;
+ }
+
switch (rx_msg_type) {
case PUCAN_MSG_CAN_RX:
err = pcan_usb_fd_decode_canmsg(usb_if, rx_msg);
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
index f736196383ac..39c86917cb5e 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
@@ -534,12 +534,18 @@ static int pcan_usb_pro_handle_canmsg(struct pcan_usb_pro_interface *usb_if,
struct pcan_usb_pro_rxmsg *rx)
{
const unsigned int ctrl_idx = (rx->len >> 4) & 0x0f;
- struct peak_usb_device *dev = usb_if->dev[ctrl_idx];
- struct net_device *netdev = dev->netdev;
+ struct peak_usb_device *dev;
+ struct net_device *netdev;
struct can_frame *can_frame;
struct sk_buff *skb;
struct skb_shared_hwtstamps *hwts;
+ if (ctrl_idx >= ARRAY_SIZE(usb_if->dev))
+ return -EINVAL;
+
+ dev = usb_if->dev[ctrl_idx];
+ netdev = dev->netdev;
+
skb = alloc_can_skb(netdev, &can_frame);
if (!skb)
return -ENOMEM;
@@ -573,14 +579,20 @@ static int pcan_usb_pro_handle_error(struct pcan_usb_pro_interface *usb_if,
{
const u16 raw_status = le16_to_cpu(er->status);
const unsigned int ctrl_idx = (er->channel >> 4) & 0x0f;
- struct peak_usb_device *dev = usb_if->dev[ctrl_idx];
- struct net_device *netdev = dev->netdev;
+ struct peak_usb_device *dev;
+ struct net_device *netdev;
struct can_frame *can_frame;
enum can_state new_state = CAN_STATE_ERROR_ACTIVE;
u8 err_mask = 0;
struct sk_buff *skb;
struct skb_shared_hwtstamps *hwts;
+ if (ctrl_idx >= ARRAY_SIZE(usb_if->dev))
+ return -EINVAL;
+
+ dev = usb_if->dev[ctrl_idx];
+ netdev = dev->netdev;
+
/* nothing should be sent while in BUS_OFF state */
if (dev->can.state == CAN_STATE_BUS_OFF)
return 0;
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 8d889bc5f3d1..aaa5640ad0f1 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -233,12 +233,6 @@ mt7530_write(struct mt7530_priv *priv, u32 reg, u32 val)
mt7530_mutex_unlock(priv);
}
-static u32
-_mt7530_unlocked_read(struct mt7530_dummy_poll *p)
-{
- return mt7530_mii_read(p->priv, p->reg);
-}
-
static u32
_mt7530_read(struct mt7530_dummy_poll *p)
{
@@ -628,16 +622,13 @@ static int
mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad,
int regnum)
{
- struct mt7530_dummy_poll p;
u32 reg, val;
int ret;
- INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);
-
mt7530_mutex_lock(priv);
- ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
- !(val & MT7531_PHY_ACS_ST), 20, 100000);
+ ret = regmap_read_poll_timeout(priv->regmap, MT7531_PHY_IAC, val,
+ !(val & MT7531_PHY_ACS_ST), 20, 100000);
if (ret < 0) {
dev_err(priv->dev, "poll timeout\n");
goto out;
@@ -647,8 +638,8 @@ mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad,
MT7531_MDIO_DEV_ADDR(devad) | regnum;
mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
- ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
- !(val & MT7531_PHY_ACS_ST), 20, 100000);
+ ret = regmap_read_poll_timeout(priv->regmap, MT7531_PHY_IAC, val,
+ !(val & MT7531_PHY_ACS_ST), 20, 100000);
if (ret < 0) {
dev_err(priv->dev, "poll timeout\n");
goto out;
@@ -658,8 +649,8 @@ mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad,
MT7531_MDIO_DEV_ADDR(devad);
mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
- ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
- !(val & MT7531_PHY_ACS_ST), 20, 100000);
+ ret = regmap_read_poll_timeout(priv->regmap, MT7531_PHY_IAC, val,
+ !(val & MT7531_PHY_ACS_ST), 20, 100000);
if (ret < 0) {
dev_err(priv->dev, "poll timeout\n");
goto out;
@@ -676,16 +667,13 @@ static int
mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad,
int regnum, u16 data)
{
- struct mt7530_dummy_poll p;
u32 val, reg;
int ret;
- INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);
-
mt7530_mutex_lock(priv);
- ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
- !(val & MT7531_PHY_ACS_ST), 20, 100000);
+ ret = regmap_read_poll_timeout(priv->regmap, MT7531_PHY_IAC, val,
+ !(val & MT7531_PHY_ACS_ST), 20, 100000);
if (ret < 0) {
dev_err(priv->dev, "poll timeout\n");
goto out;
@@ -695,8 +683,8 @@ mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad,
MT7531_MDIO_DEV_ADDR(devad) | regnum;
mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
- ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
- !(val & MT7531_PHY_ACS_ST), 20, 100000);
+ ret = regmap_read_poll_timeout(priv->regmap, MT7531_PHY_IAC, val,
+ !(val & MT7531_PHY_ACS_ST), 20, 100000);
if (ret < 0) {
dev_err(priv->dev, "poll timeout\n");
goto out;
@@ -706,8 +694,8 @@ mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad,
MT7531_MDIO_DEV_ADDR(devad) | data;
mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
- ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
- !(val & MT7531_PHY_ACS_ST), 20, 100000);
+ ret = regmap_read_poll_timeout(priv->regmap, MT7531_PHY_IAC, val,
+ !(val & MT7531_PHY_ACS_ST), 20, 100000);
if (ret < 0) {
dev_err(priv->dev, "poll timeout\n");
goto out;
@@ -722,16 +710,13 @@ mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad,
static int
mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum)
{
- struct mt7530_dummy_poll p;
int ret;
u32 val;
- INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);
-
mt7530_mutex_lock(priv);
- ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
- !(val & MT7531_PHY_ACS_ST), 20, 100000);
+ ret = regmap_read_poll_timeout(priv->regmap, MT7531_PHY_IAC, val,
+ !(val & MT7531_PHY_ACS_ST), 20, 100000);
if (ret < 0) {
dev_err(priv->dev, "poll timeout\n");
goto out;
@@ -742,8 +727,8 @@ mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum)
mt7530_mii_write(priv, MT7531_PHY_IAC, val | MT7531_PHY_ACS_ST);
- ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
- !(val & MT7531_PHY_ACS_ST), 20, 100000);
+ ret = regmap_read_poll_timeout(priv->regmap, MT7531_PHY_IAC, val,
+ !(val & MT7531_PHY_ACS_ST), 20, 100000);
if (ret < 0) {
dev_err(priv->dev, "poll timeout\n");
goto out;
@@ -760,16 +745,13 @@ static int
mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum,
u16 data)
{
- struct mt7530_dummy_poll p;
int ret;
u32 reg;
- INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);
-
mt7530_mutex_lock(priv);
- ret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg,
- !(reg & MT7531_PHY_ACS_ST), 20, 100000);
+ ret = regmap_read_poll_timeout(priv->regmap, MT7531_PHY_IAC, reg,
+ !(reg & MT7531_PHY_ACS_ST), 20, 100000);
if (ret < 0) {
dev_err(priv->dev, "poll timeout\n");
goto out;
@@ -780,8 +762,8 @@ mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum,
mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
- ret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg,
- !(reg & MT7531_PHY_ACS_ST), 20, 100000);
+ ret = regmap_read_poll_timeout(priv->regmap, MT7531_PHY_IAC, reg,
+ !(reg & MT7531_PHY_ACS_ST), 20, 100000);
if (ret < 0) {
dev_err(priv->dev, "poll timeout\n");
goto out;
diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h
index f6e43cf96a46..84fb3deca21f 100644
--- a/drivers/net/ethernet/google/gve/gve.h
+++ b/drivers/net/ethernet/google/gve/gve.h
@@ -10,6 +10,7 @@
#include <linux/dma-mapping.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
+#include <linux/timer.h>
#include <linux/u64_stats_sync.h>
#include <net/xdp.h>
@@ -36,6 +37,7 @@
/* Interval to schedule a stats report update, 20000ms. */
#define GVE_STATS_REPORT_TIMER_PERIOD 20000
+#define GVE_RX_NAPI_RESCHED_MS 20 /* msecs */
/* Numbers of NIC tx/rx stats in stats report. */
#define NIC_TX_STATS_REPORT_NUM 0
@@ -281,6 +283,7 @@ struct gve_rx_ring {
struct xdp_rxq_info xsk_rxq;
struct xsk_buff_pool *xsk_pool;
struct page_frag_cache page_cache; /* Page cache to allocate XDP frames */
+ struct timer_list starvation_timer; /* for queue starvation recovery */
};
/* A TX desc ring entry */
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
index 08f444ee10c7..9a287a376479 100644
--- a/drivers/net/ethernet/google/gve/gve_main.c
+++ b/drivers/net/ethernet/google/gve/gve_main.c
@@ -583,6 +583,9 @@ static void gve_remove_napi(struct gve_priv *priv, int ntfy_idx)
{
struct gve_notify_block *block = &priv->ntfy_blocks[ntfy_idx];
+ if (block->rx && !gve_is_gqi(priv))
+ timer_shutdown_sync(&block->rx->starvation_timer);
+
netif_napi_del(&block->napi);
disable_irq(block->irq);
}
diff --git a/drivers/net/ethernet/google/gve/gve_rx_dqo.c b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
index 3d60ea25711f..12520c9813ac 100644
--- a/drivers/net/ethernet/google/gve/gve_rx_dqo.c
+++ b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
@@ -16,6 +16,16 @@
#include <net/ipv6.h>
#include <net/tcp.h>
+static void gve_rx_starvation_timer(struct timer_list *t)
+{
+ struct gve_rx_ring *rx = from_timer(rx, t, starvation_timer);
+ struct gve_priv *priv = rx->gve;
+ struct gve_notify_block *block;
+
+ block = &priv->ntfy_blocks[rx->ntfy_id];
+ napi_schedule(&block->napi);
+}
+
static int gve_buf_ref_cnt(struct gve_rx_buf_state_dqo *bs)
{
return page_count(bs->page_info.page) - bs->page_info.pagecnt_bias;
@@ -211,6 +221,7 @@ static void gve_rx_free_ring_dqo(struct gve_priv *priv, int idx)
completion_queue_slots = rx->dqo.complq.mask + 1;
buffer_queue_slots = rx->dqo.bufq.mask + 1;
+ timer_shutdown_sync(&rx->starvation_timer);
gve_rx_remove_from_block(priv, idx);
if (rx->q_resources) {
@@ -268,6 +279,7 @@ static int gve_rx_alloc_ring_dqo(struct gve_priv *priv, int idx)
memset(rx, 0, sizeof(*rx));
rx->gve = priv;
rx->q_num = idx;
+ timer_setup(&rx->starvation_timer, gve_rx_starvation_timer, 0);
rx->dqo.bufq.mask = buffer_queue_slots - 1;
rx->dqo.complq.num_free_slots = completion_queue_slots;
rx->dqo.complq.mask = completion_queue_slots - 1;
@@ -374,6 +386,7 @@ void gve_rx_post_buffers_dqo(struct gve_rx_ring *rx)
struct gve_rx_compl_queue_dqo *complq = &rx->dqo.complq;
struct gve_rx_buf_queue_dqo *bufq = &rx->dqo.bufq;
struct gve_priv *priv = rx->gve;
+ u32 num_bufs_avail_to_hw;
u32 num_avail_slots;
u32 num_full_slots;
u32 num_posted = 0;
@@ -414,6 +427,26 @@ void gve_rx_post_buffers_dqo(struct gve_rx_ring *rx)
}
rx->fill_cnt += num_posted;
+
+ /* If the queue has fewer than GVE_RX_BUF_THRESH_DQO descriptors
+ * visible to the hardware, the hardware is in danger of starving
+ * and cannot trigger interrupts.
+ *
+ * We use a threshold of 32 because a single maximum-sized RSC
+ * packet can consume up to 19 descriptors in the Rx path. Lower
+ * thresholds (e.g., 8 or 16) would be unsafe as they could cause
+ * the device to drop/stall on a maximum-sized RSC packet.
+ *
+ * Start the timer to periodically reschedule NAPI and recover.
+ */
+ num_bufs_avail_to_hw =
+ ((bufq->tail & ~(GVE_RX_BUF_THRESH_DQO - 1)) -
+ bufq->head) & bufq->mask;
+
+ if (num_bufs_avail_to_hw < GVE_RX_BUF_THRESH_DQO) {
+ mod_timer(&rx->starvation_timer,
+ jiffies + msecs_to_jiffies(GVE_RX_NAPI_RESCHED_MS));
+ }
}
static void gve_try_recycle_buf(struct gve_priv *priv, struct gve_rx_ring *rx,
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 8dcb5d7c5a4b..97adcf50c89a 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -1228,11 +1228,11 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (hw->flash_address)
iounmap(hw->flash_address);
+err_mdio_ioremap:
kfree(adapter->tx_ring);
kfree(adapter->rx_ring);
err_dma:
err_sw_init:
-err_mdio_ioremap:
iounmap(hw->ce4100_gbe_mdio_base_virt);
iounmap(hw->hw_addr);
err_ioremap:
diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c
index 988788d21dd5..f99d2ec3c5d1 100644
--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c
+++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c
@@ -659,18 +659,18 @@ static int ice_lbtest_prepare_rings(struct ice_vsi *vsi)
status = ice_vsi_cfg_lan(vsi);
if (status)
- goto err_setup_rx_ring;
+ goto err_cfg_lan;
status = ice_vsi_start_all_rx_rings(vsi);
if (status)
- goto err_start_rx_ring;
+ goto err_cfg_lan;
return 0;
-err_start_rx_ring:
- ice_vsi_free_rx_rings(vsi);
-err_setup_rx_ring:
+err_cfg_lan:
ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, 0);
+err_setup_rx_ring:
+ ice_vsi_free_rx_rings(vsi);
err_setup_tx_ring:
ice_vsi_free_tx_rings(vsi);
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 6e0e64cc58e1..e534753657a7 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5491,6 +5491,16 @@ static int __maybe_unused ice_resume(struct device *dev)
/* Restart the service task */
mod_timer(&pf->serv_tmr, round_jiffies(jiffies + pf->serv_tmr_period));
+ /* Best-effort wait for the scheduled reset to finish so that the
+ * device is operational before returning. Without this, userspace
+ * (e.g. NetworkManager) may try to open the net device while the
+ * asynchronous reset is still in progress, hitting -EBUSY.
+ */
+ ret = ice_wait_for_reset(pf, secs_to_jiffies(10));
+ if (ret)
+ dev_err(dev, "Wait for reset timed out (10s) during resume: %d\n",
+ ret);
+
return 0;
}
#endif /* CONFIG_PM */
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index c5012fa36af2..404e8dbe679f 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -2201,8 +2201,6 @@ static inline int igbvf_tx_map_adv(struct igbvf_adapter *adapter,
buffer_info->time_stamp = 0;
buffer_info->length = 0;
buffer_info->mapped_as_page = false;
- if (count)
- count--;
/* clear timestamp and dma mappings for remaining portion of packet */
while (count--) {
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index caea58f8fd86..eb7ad5b3b629 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -842,8 +842,8 @@ static void otx2_handle_link_event(struct otx2_nic *pf)
netif_carrier_on(netdev);
netif_tx_start_all_queues(netdev);
} else {
- netif_tx_stop_all_queues(netdev);
netif_carrier_off(netdev);
+ netif_tx_stop_all_queues(netdev);
}
}
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index 7a549b834e97..0e9afeb070ba 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -6199,10 +6199,10 @@ static void nv_remove(struct pci_dev *pci_dev)
struct net_device *dev = pci_get_drvdata(pci_dev);
struct fe_priv *np = netdev_priv(dev);
- free_percpu(np->txrx_stats);
-
unregister_netdev(dev);
+ free_percpu(np->txrx_stats);
+
nv_restore_mac_addr(pci_dev);
/* restore any phy related changes */
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index b5d744d2586f..59a80f719372 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -107,7 +107,7 @@ static void qede_remove(struct pci_dev *pdev);
static void qede_shutdown(struct pci_dev *pdev);
static void qede_link_update(void *dev, struct qed_link_output *link);
static void qede_schedule_recovery_handler(void *dev);
-static void qede_recovery_handler(struct qede_dev *edev);
+static bool qede_recovery_handler(struct qede_dev *edev);
static void qede_schedule_hw_err_handler(void *dev,
enum qed_hw_err_type err_type);
static void qede_get_eth_tlv_data(void *edev, void *data);
@@ -1065,21 +1065,6 @@ void __qede_unlock(struct qede_dev *edev)
mutex_unlock(&edev->qede_lock);
}
-/* This version of the lock should be used when acquiring the RTNL lock is also
- * needed in addition to the internal qede lock.
- */
-static void qede_lock(struct qede_dev *edev)
-{
- rtnl_lock();
- __qede_lock(edev);
-}
-
-static void qede_unlock(struct qede_dev *edev)
-{
- __qede_unlock(edev);
- rtnl_unlock();
-}
-
static void qede_periodic_task(struct work_struct *work)
{
struct qede_dev *edev = container_of(work, struct qede_dev,
@@ -1116,6 +1101,8 @@ static void qede_sp_task(struct work_struct *work)
*/
if (test_and_clear_bit(QEDE_SP_RECOVERY, &edev->sp_flags)) {
+ bool reloaded;
+
cancel_delayed_work_sync(&edev->periodic_task);
#ifdef CONFIG_QED_SRIOV
/* SRIOV must be disabled outside the lock to avoid a deadlock.
@@ -1124,9 +1111,17 @@ static void qede_sp_task(struct work_struct *work)
if (pci_num_vf(edev->pdev))
qede_sriov_configure(edev->pdev, 0);
#endif
- qede_lock(edev);
- qede_recovery_handler(edev);
- qede_unlock(edev);
+ rtnl_lock();
+ __qede_lock(edev);
+ reloaded = qede_recovery_handler(edev);
+ __qede_unlock(edev);
+
+ /* The udp_tunnel core synchronously calls back into
+ * qede_udp_tunnel_sync(), which takes the qede lock.
+ */
+ if (reloaded)
+ udp_tunnel_nic_reset_ntf(edev->ndev);
+ rtnl_unlock();
}
__qede_lock(edev);
@@ -2667,9 +2662,13 @@ static void qede_recovery_failed(struct qede_dev *edev)
edev->ops->common->set_power_state(edev->cdev, PCI_D3hot);
}
-static void qede_recovery_handler(struct qede_dev *edev)
+/* Returns true if an open device was successfully reloaded and its
+ * udp_tunnel ports need to be re-synced by the caller.
+ */
+static bool qede_recovery_handler(struct qede_dev *edev)
{
u32 curr_state = edev->state;
+ bool reloaded = false;
int rc;
DP_NOTICE(edev, "Starting a recovery process\n");
@@ -2699,17 +2698,18 @@ static void qede_recovery_handler(struct qede_dev *edev)
goto err;
qede_config_rx_mode(edev->ndev);
- udp_tunnel_nic_reset_ntf(edev->ndev);
+ reloaded = true;
}
edev->state = curr_state;
DP_NOTICE(edev, "Recovery handling is done\n");
- return;
+ return reloaded;
err:
qede_recovery_failed(edev);
+ return false;
}
static void qede_atomic_hw_err_handler(struct qede_dev *edev)
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
index d662679c2983..df300493a8d9 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -599,14 +599,13 @@ static int init_dma_desc_rings(struct net_device *netd)
return 0;
-txalloc_err:
- while (queue_num--)
- free_tx_ring(priv->device, priv->txq[queue_num], tx_rsize);
- return ret;
-
rxalloc_err:
while (queue_num--)
free_rx_ring(priv->device, priv->rxq[queue_num], rx_rsize);
+ queue_num = SXGBE_TX_QUEUES;
+txalloc_err:
+ while (queue_num--)
+ free_tx_ring(priv->device, priv->txq[queue_num], tx_rsize);
return ret;
}
@@ -1081,7 +1080,9 @@ static int sxgbe_open(struct net_device *dev)
priv->dma_buf_sz = SXGBE_ALIGN(DMA_BUFFER_SIZE);
priv->tx_tc = TC_DEFAULT;
priv->rx_tc = TC_DEFAULT;
- init_dma_desc_rings(dev);
+ ret = init_dma_desc_rings(dev);
+ if (ret)
+ goto init_phy_error;
/* DMA initialization and SW reset */
ret = sxgbe_init_dma_engine(priv);
@@ -1190,6 +1191,7 @@ static int sxgbe_open(struct net_device *dev)
init_error:
free_dma_desc_resources(priv);
+init_phy_error:
if (dev->phydev)
phy_disconnect(dev->phydev);
phy_error:
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 800e8b9eb453..6d8ff73a7eba 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1635,8 +1635,8 @@ struct phylink *phylink_create(struct phylink_config *config,
} else if (config->type == PHYLINK_DEV) {
pl->dev = config->dev;
} else {
- kfree(pl);
- return ERR_PTR(-EINVAL);
+ ret = -EINVAL;
+ goto free_pl;
}
pl->using_mac_select_pcs = using_mac_select_pcs;
@@ -1660,28 +1660,29 @@ struct phylink *phylink_create(struct phylink_config *config,
phylink_validate(pl, pl->supported, &pl->link_config);
ret = phylink_parse_mode(pl, fwnode);
- if (ret < 0) {
- kfree(pl);
- return ERR_PTR(ret);
- }
+ if (ret < 0)
+ goto free_pl;
if (pl->cfg_link_an_mode == MLO_AN_FIXED) {
ret = phylink_parse_fixedlink(pl, fwnode);
- if (ret < 0) {
- kfree(pl);
- return ERR_PTR(ret);
- }
+ if (ret < 0)
+ goto release_link_gpio;
}
pl->cur_link_an_mode = pl->cfg_link_an_mode;
ret = phylink_register_sfp(pl, fwnode);
- if (ret < 0) {
- kfree(pl);
- return ERR_PTR(ret);
- }
+ if (ret < 0)
+ goto release_link_gpio;
return pl;
+
+release_link_gpio:
+ if (pl->link_gpio)
+ gpiod_put(pl->link_gpio);
+free_pl:
+ kfree(pl);
+ return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(phylink_create);
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 9f7b05a01051..bce55ad2bcd9 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -1983,7 +1983,7 @@ static int vrf_netns_init_sysctl(struct net *net, struct netns_vrf *nn_vrf)
static void vrf_netns_exit_sysctl(struct net *net)
{
struct netns_vrf *nn_vrf = net_generic(net, vrf_net_id);
- struct ctl_table *table;
+ const struct ctl_table *table;
table = nn_vrf->ctl_hdr->ctl_table_arg;
unregister_net_sysctl_table(nn_vrf->ctl_hdr);
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 4fcf5c123a9d..0e9aeb03fcc7 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -2111,7 +2111,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
{
struct iphdr *pip;
- if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+ if (!pskb_network_may_pull(skb, sizeof(struct iphdr)))
return false;
pip = ip_hdr(skb);
n = neigh_lookup(&arp_tbl, &pip->daddr, dev);
@@ -2137,7 +2137,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
*/
if (!ipv6_stub->nd_tbl)
return false;
- if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+ if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr)))
return false;
pip6 = ipv6_hdr(skb);
n = neigh_lookup(ipv6_stub->nd_tbl, &pip6->daddr, dev);
@@ -2159,13 +2159,19 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
}
if (n) {
+ u8 haddr[ETH_ALEN];
bool diff;
- diff = !ether_addr_equal(eth_hdr(skb)->h_dest, n->ha);
+ neigh_ha_snapshot(haddr, n, dev);
+ diff = !ether_addr_equal_unaligned(eth_hdr(skb)->h_dest, haddr);
if (diff) {
+ if (skb_cow_head(skb, 0)) {
+ neigh_release(n);
+ return false;
+ }
memcpy(eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
dev->addr_len);
- memcpy(eth_hdr(skb)->h_dest, n->ha, dev->addr_len);
+ memcpy(eth_hdr(skb)->h_dest, haddr, dev->addr_len);
}
neigh_release(n);
return diff;
@@ -2863,6 +2869,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
(ntohs(eth->h_proto) == ETH_P_IP ||
ntohs(eth->h_proto) == ETH_P_IPV6)) {
did_rsc = route_shortcircuit(dev, skb);
+ eth = eth_hdr(skb);
if (did_rsc)
f = vxlan_find_mac(vxlan, eth->h_dest, vni);
}
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c
index 159ec376baff..0075992ad3d1 100644
--- a/drivers/net/wireless/ath/ath6kl/txrx.c
+++ b/drivers/net/wireless/ath/ath6kl/txrx.c
@@ -1829,7 +1829,7 @@ void aggr_reset_state(struct aggr_info_conn *aggr_conn)
return;
if (aggr_conn->timer_scheduled) {
- del_timer(&aggr_conn->timer);
+ timer_delete_sync(&aggr_conn->timer);
aggr_conn->timer_scheduled = false;
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index 14f3c4900f56..c1d600ed18f1 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -906,6 +906,7 @@ int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
return ret;
}
switch (sdiodev->func2->device) {
+ case SDIO_DEVICE_ID_BROADCOM_43752:
case SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373:
f2_blksz = SDIO_4373_FUNC2_BLOCKSIZE;
break;
@@ -991,9 +992,9 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = {
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354, WCC),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4356, WCC),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4359, WCC),
+ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43752, WCC),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373, CYW),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43012, CYW),
- BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752, CYW),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_89359, CYW),
CYW_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43439, CYW),
{ /* end: all zeroes */ }
@@ -1064,6 +1065,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
bus_if = kzalloc(sizeof(struct brcmf_bus), GFP_KERNEL);
if (!bus_if)
return -ENOMEM;
+ mutex_init(&bus_if->bus_reset_lock);
sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL);
if (!sdiodev) {
kfree(bus_if);
@@ -1125,6 +1127,14 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func)
if (func->num != 1)
return;
+ /* Drain bus_reset before the shared brcmf_sdiod_remove()
+ * teardown, which the SDIO reset callback also reaches. The
+ * data worker can arm bus_reset via brcmf_fw_crashed(); cancel
+ * it first.
+ */
+ brcmf_sdio_cancel_datawork(sdiodev->bus);
+ brcmf_bus_cancel_reset_work(bus_if);
+
/* only proceed with rest of cleanup if func 1 */
brcmf_sdiod_remove(sdiodev);
@@ -1199,6 +1209,8 @@ static int brcmf_ops_sdio_suspend(struct device *dev)
} else {
/* power will be cut so remove device, probe again in resume */
brcmf_sdiod_intr_unregister(sdiodev);
+ brcmf_sdio_cancel_datawork(sdiodev->bus);
+ brcmf_bus_cancel_reset_work(bus_if);
ret = brcmf_sdiod_remove(sdiodev);
if (ret)
brcmf_err("Failed to remove device on suspend\n");
@@ -1224,6 +1236,8 @@ static int brcmf_ops_sdio_resume(struct device *dev)
ret = brcmf_sdiod_probe(sdiodev);
if (ret)
brcmf_err("Failed to probe device on resume\n");
+ else
+ brcmf_bus_allow_reset_work(bus_if);
} else {
if (sdiodev->wowl_enabled && sdiodev->settings->bus.sdio.oob_irq_supported)
disable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
index fe31051a9e11..9371c1489948 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <linux/firmware.h>
#include <linux/device.h>
+#include <linux/mutex.h>
#include "debug.h"
/* IDs of the 6 default common rings of msgbuf protocol */
@@ -179,6 +180,8 @@ struct brcmf_bus {
enum brcmf_fwvendor fwvid;
bool always_use_fws_queue;
bool wowl_supported;
+ bool removing; /* device removal in progress; quiesce async work */
+ struct mutex bus_reset_lock;
const struct brcmf_bus_ops *ops;
struct brcmf_bus_msgbuf *msgbuf;
@@ -186,6 +189,9 @@ struct brcmf_bus {
struct list_head list;
};
+void brcmf_bus_cancel_reset_work(struct brcmf_bus *bus_if);
+void brcmf_bus_allow_reset_work(struct brcmf_bus *bus_if);
+
/*
* callback wrappers
*/
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
index 4dbb1898f306..e3a01a28a182 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
@@ -738,7 +738,7 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci)
case BRCM_CC_4364_CHIP_ID:
case CY_CC_4373_CHIP_ID:
return 0x160000;
- case CY_CC_43752_CHIP_ID:
+ case BRCM_CC_43752_CHIP_ID:
case BRCM_CC_4377_CHIP_ID:
return 0x170000;
case BRCM_CC_4378_CHIP_ID:
@@ -1465,7 +1465,7 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub)
reg = chip->ops->read32(chip->ctx, addr);
return (reg & CC_SR_CTL0_ENABLE_MASK) != 0;
case BRCM_CC_4359_CHIP_ID:
- case CY_CC_43752_CHIP_ID:
+ case BRCM_CC_43752_CHIP_ID:
case CY_CC_43012_CHIP_ID:
addr = CORE_CC_REG(pmu->base, retention_ctl);
reg = chip->ops->read32(chip->ctx, addr);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index 96f607f35490..fff7a3ace5c4 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -1162,6 +1162,35 @@ static int brcmf_revinfo_read(struct seq_file *s, void *data)
return 0;
}
+/*
+ * Serialize arming from debugfs reset and brcmf_fw_crashed() against
+ * teardown. The remove path sets ->removing and drains the work while
+ * holding bus_reset_lock, so a racing armer is either drained or skips it.
+ */
+static void brcmf_bus_schedule_reset(struct brcmf_bus *bus_if)
+{
+ mutex_lock(&bus_if->bus_reset_lock);
+ if (bus_if->drvr && bus_if->drvr->bus_reset.func && !bus_if->removing)
+ schedule_work(&bus_if->drvr->bus_reset);
+ mutex_unlock(&bus_if->bus_reset_lock);
+}
+
+void brcmf_bus_cancel_reset_work(struct brcmf_bus *bus_if)
+{
+ mutex_lock(&bus_if->bus_reset_lock);
+ bus_if->removing = true;
+ if (bus_if->drvr)
+ cancel_work_sync(&bus_if->drvr->bus_reset);
+ mutex_unlock(&bus_if->bus_reset_lock);
+}
+
+void brcmf_bus_allow_reset_work(struct brcmf_bus *bus_if)
+{
+ mutex_lock(&bus_if->bus_reset_lock);
+ bus_if->removing = false;
+ mutex_unlock(&bus_if->bus_reset_lock);
+}
+
static void brcmf_core_bus_reset(struct work_struct *work)
{
struct brcmf_pub *drvr = container_of(work, struct brcmf_pub,
@@ -1182,7 +1211,7 @@ static ssize_t bus_reset_write(struct file *file, const char __user *user_buf,
if (value != 1)
return -EINVAL;
- schedule_work(&drvr->bus_reset);
+ brcmf_bus_schedule_reset(drvr->bus_if);
return count;
}
@@ -1407,14 +1436,23 @@ void brcmf_dev_coredump(struct device *dev)
void brcmf_fw_crashed(struct device *dev)
{
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- struct brcmf_pub *drvr = bus_if->drvr;
+ struct brcmf_pub *drvr;
+
+ /* May fire before brcmf_attach() wires up drvr, or after removal
+ * has cleared it; guard the derefs below (and the arming gate in
+ * brcmf_bus_schedule_reset() already checks drvr/->removing).
+ */
+ if (!bus_if)
+ return;
+ drvr = bus_if->drvr;
+ if (!drvr)
+ return;
bphy_err(drvr, "Firmware has halted or crashed\n");
brcmf_dev_coredump(dev);
- if (drvr->bus_reset.func)
- schedule_work(&drvr->bus_reset);
+ brcmf_bus_schedule_reset(bus_if);
}
void brcmf_detach(struct device *dev)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index cbb6d512c43b..0939ddb5559a 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -2467,6 +2467,7 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ret = -ENOMEM;
goto fail;
}
+ mutex_init(&bus->bus_reset_lock);
bus->msgbuf = kzalloc(sizeof(*bus->msgbuf), GFP_KERNEL);
if (!bus->msgbuf) {
ret = -ENOMEM;
@@ -2552,6 +2553,11 @@ brcmf_pcie_remove(struct pci_dev *pdev)
if (devinfo->ci)
brcmf_pcie_intr_disable(devinfo);
+ if (devinfo->irq_allocated)
+ synchronize_irq(pdev->irq);
+
+ brcmf_bus_cancel_reset_work(bus);
+
brcmf_detach(&pdev->dev);
brcmf_free(&pdev->dev);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 1ab0f501017b..0877507abd3c 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -654,10 +654,10 @@ static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
BRCMF_FW_ENTRY(BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, 4354),
BRCMF_FW_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356),
BRCMF_FW_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359),
+ BRCMF_FW_ENTRY(BRCM_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752),
BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373),
BRCMF_FW_ENTRY(CY_CC_43012_CHIP_ID, 0xFFFFFFFF, 43012),
BRCMF_FW_ENTRY(CY_CC_43439_CHIP_ID, 0xFFFFFFFF, 43439),
- BRCMF_FW_ENTRY(CY_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752)
};
#define TXCTL_CREDITS 2
@@ -3425,8 +3425,8 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus,
static bool brcmf_sdio_aos_no_decode(struct brcmf_sdio *bus)
{
- if (bus->ci->chip == CY_CC_43012_CHIP_ID ||
- bus->ci->chip == CY_CC_43752_CHIP_ID)
+ if (bus->ci->chip == BRCM_CC_43752_CHIP_ID ||
+ bus->ci->chip == CY_CC_43012_CHIP_ID)
return true;
else
return false;
@@ -4274,8 +4274,8 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err,
bus->hostintmask, NULL);
switch (sdiod->func1->device) {
+ case SDIO_DEVICE_ID_BROADCOM_43752:
case SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373:
- case SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752:
brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n",
CY_4373_F2_WATERMARK);
brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
@@ -4550,6 +4550,12 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
return NULL;
}
+void brcmf_sdio_cancel_datawork(struct brcmf_sdio *bus)
+{
+ if (bus)
+ cancel_work_sync(&bus->datawork);
+}
+
/* Detach and free everything */
void brcmf_sdio_remove(struct brcmf_sdio *bus)
{
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
index 0d18ed15b403..927fb82dec9c 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -361,6 +361,7 @@ int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev);
struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev);
void brcmf_sdio_remove(struct brcmf_sdio *bus);
void brcmf_sdio_isr(struct brcmf_sdio *bus, bool in_isr);
+void brcmf_sdio_cancel_datawork(struct brcmf_sdio *bus);
void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, bool active);
void brcmf_sdio_wowl_config(struct device *dev, bool enabled);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
index 6f64a05debd2..906591bae538 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
@@ -1261,6 +1261,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,
ret = -ENOMEM;
goto fail;
}
+ mutex_init(&bus->bus_reset_lock);
bus->dev = dev;
bus_pub->bus = bus;
@@ -1327,6 +1328,8 @@ brcmf_usb_disconnect_cb(struct brcmf_usbdev_info *devinfo)
return;
brcmf_dbg(USB, "Enter, bus_pub %p\n", devinfo);
+ brcmf_bus_cancel_reset_work(devinfo->bus_pub.bus);
+
brcmf_detach(devinfo->dev);
brcmf_free(devinfo->dev);
kfree(devinfo->bus_pub.bus);
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
index 44684bf1b9ac..2f886af068c5 100644
--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
@@ -52,13 +52,13 @@
#define BRCM_CC_43664_CHIP_ID 43664
#define BRCM_CC_43666_CHIP_ID 43666
#define BRCM_CC_4371_CHIP_ID 0x4371
+#define BRCM_CC_43752_CHIP_ID 43752
#define BRCM_CC_4377_CHIP_ID 0x4377
#define BRCM_CC_4378_CHIP_ID 0x4378
#define BRCM_CC_4387_CHIP_ID 0x4387
#define CY_CC_4373_CHIP_ID 0x4373
#define CY_CC_43012_CHIP_ID 43012
#define CY_CC_43439_CHIP_ID 43439
-#define CY_CC_43752_CHIP_ID 43752
/* USB Device IDs */
#define BRCM_USB_43143_DEVICE_ID 0xbd1e
diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
index 99f888bfd105..ae1525e8ee1f 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
@@ -44,7 +44,7 @@ static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv,
ntohs(rx_hdr->eth803_hdr.h_proto) == ETH_P_TDLS) {
mwifiex_process_tdls_action_frame(priv,
(u8 *)rx_hdr,
- skb->len);
+ rx_skb->len);
}
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
diff --git a/drivers/phy/xilinx/phy-zynqmp.c b/drivers/phy/xilinx/phy-zynqmp.c
index c72b52955a86..6522611df084 100644
--- a/drivers/phy/xilinx/phy-zynqmp.c
+++ b/drivers/phy/xilinx/phy-zynqmp.c
@@ -52,7 +52,7 @@
#define L0_TM_DIG_6 0x106c
#define L0_TM_DIS_DESCRAMBLE_DECODER 0x0f
#define L0_TX_DIG_61 0x00f4
-#define L0_TM_DISABLE_SCRAMBLE_ENCODER 0x0f
+#define L0_TM_DISABLE_SCRAMBLE_ENCODER (BIT(3) | GENMASK(1, 0))
/* PLL Test Mode register parameters */
#define L0_TM_PLL_DIG_37 0x2094
@@ -227,7 +227,6 @@ struct xpsgtr_phy {
* @siou: siou base address
* @gtr_mutex: mutex for locking
* @phys: PHY lanes
- * @refclk_sscs: spread spectrum settings for the reference clocks
* @clk: reference clocks
* @tx_term_fix: fix for GT issue
* @saved_icm_cfg0: stored value of ICM CFG0 register
@@ -240,7 +239,6 @@ struct xpsgtr_dev {
void __iomem *siou;
struct mutex gtr_mutex; /* mutex for locking */
struct xpsgtr_phy phys[NUM_LANES];
- const struct xpsgtr_ssc *refclk_sscs[NUM_LANES];
struct clk *clk[NUM_LANES];
bool tx_term_fix;
unsigned int saved_icm_cfg0;
@@ -383,13 +381,40 @@ static int xpsgtr_wait_pll_lock(struct phy *phy)
return ret;
}
+/* Get the spread spectrum (SSC) settings for the reference clock rate */
+static const struct xpsgtr_ssc *xpsgtr_find_sscs(struct xpsgtr_phy *gtr_phy)
+{
+ unsigned long rate;
+ struct clk *clk;
+ unsigned int i;
+
+ clk = gtr_phy->dev->clk[gtr_phy->refclk];
+ rate = clk_get_rate(clk);
+
+ for (i = 0 ; i < ARRAY_SIZE(ssc_lookup); i++) {
+ /* Allow an error of 100 ppm */
+ unsigned long error = ssc_lookup[i].refclk_rate / 10000;
+
+ if (abs(rate - ssc_lookup[i].refclk_rate) < error)
+ return &ssc_lookup[i];
+ }
+
+ dev_err(gtr_phy->dev->dev, "Invalid rate %lu for reference clock %u\n",
+ rate, gtr_phy->refclk);
+
+ return NULL;
+}
+
/* Configure PLL and spread-sprectrum clock. */
-static void xpsgtr_configure_pll(struct xpsgtr_phy *gtr_phy)
+static int xpsgtr_configure_pll(struct xpsgtr_phy *gtr_phy)
{
const struct xpsgtr_ssc *ssc;
u32 step_size;
- ssc = gtr_phy->dev->refclk_sscs[gtr_phy->refclk];
+ ssc = xpsgtr_find_sscs(gtr_phy);
+ if (!ssc)
+ return -EINVAL;
+
step_size = ssc->step_size;
xpsgtr_clr_set(gtr_phy->dev, PLL_REF_SEL(gtr_phy->lane),
@@ -431,6 +456,8 @@ static void xpsgtr_configure_pll(struct xpsgtr_phy *gtr_phy)
xpsgtr_clr_set_phy(gtr_phy, L0_PLL_SS_STEP_SIZE_3_MSB,
STEP_SIZE_3_MASK, (step_size & STEP_SIZE_3_MASK) |
FORCE_STEP_SIZE | FORCE_STEPS);
+
+ return 0;
}
/* Configure the lane protocol. */
@@ -460,11 +487,30 @@ static void xpsgtr_lane_set_protocol(struct xpsgtr_phy *gtr_phy)
}
}
-/* Bypass (de)scrambler and 8b/10b decoder and encoder. */
-static void xpsgtr_bypass_scrambler_8b10b(struct xpsgtr_phy *gtr_phy)
+/**
+ * xpsgtr_bypass_scrambler_8b10b - Configure scrambler/encoder behavior
+ * @gtr_phy: pointer to lane context
+ * @bypass: true to enable scrambler/encoder bypass (SATA/SGMII),
+ * false to disable scrambler/encoder bypass (USB3)
+ *
+ * Uses RMW to preserve reserved and unrelated register fields.
+ */
+static void xpsgtr_bypass_scrambler_8b10b(struct xpsgtr_phy *gtr_phy,
+ bool bypass)
{
- xpsgtr_write_phy(gtr_phy, L0_TM_DIG_6, L0_TM_DIS_DESCRAMBLE_DECODER);
- xpsgtr_write_phy(gtr_phy, L0_TX_DIG_61, L0_TM_DISABLE_SCRAMBLE_ENCODER);
+ if (bypass) {
+ xpsgtr_clr_set_phy(gtr_phy, L0_TM_DIG_6,
+ L0_TM_DIS_DESCRAMBLE_DECODER,
+ L0_TM_DIS_DESCRAMBLE_DECODER);
+ xpsgtr_clr_set_phy(gtr_phy, L0_TX_DIG_61,
+ L0_TM_DISABLE_SCRAMBLE_ENCODER,
+ L0_TM_DISABLE_SCRAMBLE_ENCODER);
+ } else {
+ xpsgtr_clr_set_phy(gtr_phy, L0_TM_DIG_6,
+ L0_TM_DIS_DESCRAMBLE_DECODER, 0);
+ xpsgtr_clr_set_phy(gtr_phy, L0_TX_DIG_61,
+ L0_TM_DISABLE_SCRAMBLE_ENCODER, 0);
+ }
}
/* DP-specific initialization. */
@@ -485,7 +531,7 @@ static void xpsgtr_phy_init_sata(struct xpsgtr_phy *gtr_phy)
{
struct xpsgtr_dev *gtr_dev = gtr_phy->dev;
- xpsgtr_bypass_scrambler_8b10b(gtr_phy);
+ xpsgtr_bypass_scrambler_8b10b(gtr_phy, true);
writel(gtr_phy->lane, gtr_dev->siou + SATA_CONTROL_OFFSET);
}
@@ -501,7 +547,7 @@ static void xpsgtr_phy_init_sgmii(struct xpsgtr_phy *gtr_phy)
xpsgtr_clr_set(gtr_dev, TX_PROT_BUS_WIDTH, mask, val);
xpsgtr_clr_set(gtr_dev, RX_PROT_BUS_WIDTH, mask, val);
- xpsgtr_bypass_scrambler_8b10b(gtr_phy);
+ xpsgtr_bypass_scrambler_8b10b(gtr_phy, true);
}
/* Configure TX de-emphasis and margining for DP. */
@@ -616,12 +662,13 @@ static int xpsgtr_phy_init(struct phy *phy)
{
struct xpsgtr_phy *gtr_phy = phy_get_drvdata(phy);
struct xpsgtr_dev *gtr_dev = gtr_phy->dev;
- int ret = 0;
+ int ret;
mutex_lock(>r_dev->gtr_mutex);
/* Configure and enable the clock when peripheral phy_init call */
- if (clk_prepare_enable(gtr_dev->clk[gtr_phy->refclk]))
+ ret = clk_prepare_enable(gtr_dev->clk[gtr_phy->refclk]);
+ if (ret)
goto out;
/* Skip initialization if not required. */
@@ -631,7 +678,7 @@ static int xpsgtr_phy_init(struct phy *phy)
if (gtr_dev->tx_term_fix) {
ret = xpsgtr_phy_tx_term_fix(gtr_phy);
if (ret < 0)
- goto out;
+ goto out_disable_clk;
gtr_dev->tx_term_fix = false;
}
@@ -643,7 +690,10 @@ static int xpsgtr_phy_init(struct phy *phy)
* Configure the PLL, the lane protocol, and perform protocol-specific
* initialization.
*/
- xpsgtr_configure_pll(gtr_phy);
+ ret = xpsgtr_configure_pll(gtr_phy);
+ if (ret)
+ goto out_disable_clk;
+
xpsgtr_lane_set_protocol(gtr_phy);
switch (gtr_phy->protocol) {
@@ -658,8 +708,16 @@ static int xpsgtr_phy_init(struct phy *phy)
case ICM_PROTOCOL_SGMII:
xpsgtr_phy_init_sgmii(gtr_phy);
break;
+
+ case ICM_PROTOCOL_USB:
+ xpsgtr_bypass_scrambler_8b10b(gtr_phy, false);
+ break;
}
+ goto out;
+
+out_disable_clk:
+ clk_disable_unprepare(gtr_dev->clk[gtr_phy->refclk]);
out:
mutex_unlock(>r_dev->gtr_mutex);
return ret;
@@ -854,8 +912,7 @@ static struct phy *xpsgtr_xlate(struct device *dev,
}
refclk = args->args[3];
- if (refclk >= ARRAY_SIZE(gtr_dev->refclk_sscs) ||
- !gtr_dev->refclk_sscs[refclk]) {
+ if (refclk >= ARRAY_SIZE(gtr_dev->clk)) {
dev_err(dev, "Invalid reference clock number %u\n", refclk);
return ERR_PTR(-EINVAL);
}
@@ -931,9 +988,7 @@ static int xpsgtr_get_ref_clocks(struct xpsgtr_dev *gtr_dev)
{
unsigned int refclk;
- for (refclk = 0; refclk < ARRAY_SIZE(gtr_dev->refclk_sscs); ++refclk) {
- unsigned long rate;
- unsigned int i;
+ for (refclk = 0; refclk < ARRAY_SIZE(gtr_dev->clk); ++refclk) {
struct clk *clk;
char name[8];
@@ -949,29 +1004,6 @@ static int xpsgtr_get_ref_clocks(struct xpsgtr_dev *gtr_dev)
continue;
gtr_dev->clk[refclk] = clk;
-
- /*
- * Get the spread spectrum (SSC) settings for the reference
- * clock rate.
- */
- rate = clk_get_rate(clk);
-
- for (i = 0 ; i < ARRAY_SIZE(ssc_lookup); i++) {
- /* Allow an error of 100 ppm */
- unsigned long error = ssc_lookup[i].refclk_rate / 10000;
-
- if (abs(rate - ssc_lookup[i].refclk_rate) < error) {
- gtr_dev->refclk_sscs[refclk] = &ssc_lookup[i];
- break;
- }
- }
-
- if (i == ARRAY_SIZE(ssc_lookup)) {
- dev_err(gtr_dev->dev,
- "Invalid rate %lu for reference clock %u\n",
- rate, refclk);
- return -EINVAL;
- }
}
return 0;
@@ -1036,6 +1068,12 @@ static int xpsgtr_probe(struct platform_device *pdev)
return PTR_ERR(provider);
}
+ gtr_dev->saved_regs = devm_kmalloc(gtr_dev->dev,
+ sizeof(save_reg_address),
+ GFP_KERNEL);
+ if (!gtr_dev->saved_regs)
+ return -ENOMEM;
+
pm_runtime_set_active(gtr_dev->dev);
pm_runtime_enable(gtr_dev->dev);
@@ -1045,12 +1083,6 @@ static int xpsgtr_probe(struct platform_device *pdev)
return ret;
}
- gtr_dev->saved_regs = devm_kmalloc(gtr_dev->dev,
- sizeof(save_reg_address),
- GFP_KERNEL);
- if (!gtr_dev->saved_regs)
- return -ENOMEM;
-
return 0;
}
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index ab3908a923e3..de487922d521 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -132,6 +132,7 @@ config PINCTRL_BM1880
depends on OF && (ARCH_BITMAIN || COMPILE_TEST)
default ARCH_BITMAIN
select PINMUX
+ select GENERIC_PINCONF
help
Pinctrl driver for Bitmain BM1880 SoC.
@@ -326,6 +327,7 @@ config PINCTRL_MICROCHIP_SGPIO
select GENERIC_PINCTRL_GROUPS
select GENERIC_PINMUX_FUNCTIONS
select OF_GPIO
+ select REGMAP_MMIO
help
Support for the serial GPIO interface used on Microsemi and
Microchip SoCs. By using a serial interface, the SIO
diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
index 6520b88db110..bd6dc5ff53ee 100644
--- a/drivers/pinctrl/devicetree.c
+++ b/drivers/pinctrl/devicetree.c
@@ -69,6 +69,10 @@ static int dt_remember_or_free_map(struct pinctrl *p, const char *statename,
int i;
struct pinctrl_dt_map *dt_map;
+ /* Initialize dev_name before any allocation can fail */
+ for (i = 0; i < num_maps; i++)
+ map[i].dev_name = NULL;
+
/* Initialize common mapping table entry fields */
for (i = 0; i < num_maps; i++) {
const char *devname;
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index ba38173d3ed3..9c937f6cf525 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -869,8 +869,7 @@ static void amd_gpio_irq_init(struct amd_gpio *gpio_dev)
u32 pin_reg, mask;
int i;
- mask = BIT(WAKE_CNTRL_OFF_S0I3) | BIT(WAKE_CNTRL_OFF_S3) |
- BIT(WAKE_CNTRL_OFF_S4);
+ mask = BIT(WAKE_CNTRL_OFF_S0I3) | BIT(WAKE_CNTRL_OFF_S3);
for (i = 0; i < desc->npins; i++) {
int pin = desc->pins[i].number;
diff --git a/drivers/pinctrl/qcom/pinctrl-sc8280xp.c b/drivers/pinctrl/qcom/pinctrl-sc8280xp.c
index 4b1c49697698..67945ce867fa 100644
--- a/drivers/pinctrl/qcom/pinctrl-sc8280xp.c
+++ b/drivers/pinctrl/qcom/pinctrl-sc8280xp.c
@@ -1884,16 +1884,17 @@ static const struct msm_gpio_wakeirq_map sc8280xp_pdc_map[] = {
{ 126, 200 }, { 127, 225 }, { 128, 262 }, { 129, 201 },
{ 130, 209 }, { 131, 173 }, { 132, 202 }, { 136, 210 },
{ 138, 171 }, { 139, 226 }, { 140, 227 }, { 142, 228 },
- { 144, 229 }, { 145, 230 }, { 146, 231 }, { 148, 232 },
- { 149, 233 }, { 150, 234 }, { 152, 235 }, { 154, 212 },
- { 157, 213 }, { 161, 219 }, { 170, 236 }, { 171, 221 },
- { 174, 222 }, { 175, 237 }, { 176, 223 }, { 177, 170 },
- { 180, 238 }, { 181, 239 }, { 182, 240 }, { 183, 241 },
- { 184, 242 }, { 185, 243 }, { 190, 178 }, { 193, 184 },
- { 196, 185 }, { 198, 186 }, { 200, 174 }, { 201, 175 },
- { 205, 176 }, { 206, 177 }, { 208, 187 }, { 210, 198 },
- { 211, 199 }, { 212, 204 }, { 215, 205 }, { 220, 188 },
- { 221, 194 }, { 223, 195 }, { 225, 196 }, { 227, 197 },
+ { 143, 261 }, { 144, 229 }, { 145, 230 }, { 146, 231 },
+ { 148, 232 }, { 149, 233 }, { 150, 234 }, { 151, 264 },
+ { 152, 235 }, { 154, 212 }, { 157, 213 }, { 161, 219 },
+ { 170, 236 }, { 171, 221 }, { 174, 222 }, { 175, 237 },
+ { 176, 223 }, { 177, 170 }, { 180, 238 }, { 181, 239 },
+ { 182, 240 }, { 183, 241 }, { 184, 242 }, { 185, 243 },
+ { 190, 178 }, { 193, 184 }, { 196, 185 }, { 198, 186 },
+ { 200, 174 }, { 201, 175 }, { 205, 176 }, { 206, 177 },
+ { 208, 187 }, { 210, 198 }, { 211, 199 }, { 212, 204 },
+ { 215, 205 }, { 220, 188 }, { 221, 194 }, { 223, 195 },
+ { 225, 196 }, { 227, 197 },
};
static struct msm_pinctrl_soc_data sc8280xp_pinctrl = {
diff --git a/drivers/power/supply/bq25890_charger.c b/drivers/power/supply/bq25890_charger.c
index 03fa11a1c9b6..ea824f13343c 100644
--- a/drivers/power/supply/bq25890_charger.c
+++ b/drivers/power/supply/bq25890_charger.c
@@ -320,7 +320,7 @@ static const u32 bq25890_tspct_tbl[] = {
145, 140, 130, 120, 115, 110, 100, 90,
80, 70, 60, 50, 40, 30, 20, 10,
0, -10, -20, -30, -40, -60, -70, -80,
- -90, -10, -120, -140, -150, -170, -190, -210,
+ -90, -100, -120, -140, -150, -170, -190, -210,
};
#define BQ25890_TSPCT_TBL_SIZE ARRAY_SIZE(bq25890_tspct_tbl)
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 2777528f7a55..9e3c4d2de89c 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -23,6 +23,7 @@
#include <linux/seq_file.h>
#include <linux/uaccess.h>
#include <linux/io.h>
+#include <linux/overflow.h>
#include <asm/css_chars.h>
#include <asm/debug.h>
@@ -3489,11 +3490,11 @@ static int dasd_eckd_check_device_format(struct dasd_device *base,
{
struct dasd_eckd_private *private = base->private;
struct eckd_count *fmt_buffer;
- struct irb irb;
+ size_t fmt_buffer_size;
+ unsigned int trkcount;
int rpt_max, rpt_exp;
- int fmt_buffer_size;
+ struct irb irb;
int trk_per_cyl;
- int trkcount;
int tpm = 0;
int rc;
@@ -3504,7 +3505,9 @@ static int dasd_eckd_check_device_format(struct dasd_device *base,
rpt_exp = recs_per_track(&private->rdc_data, 0, cdata->expect.blksize);
trkcount = cdata->expect.stop_unit - cdata->expect.start_unit + 1;
- fmt_buffer_size = trkcount * rpt_max * sizeof(struct eckd_count);
+ if (check_mul_overflow(trkcount, rpt_max, &fmt_buffer_size) ||
+ check_mul_overflow(fmt_buffer_size, sizeof(struct eckd_count), &fmt_buffer_size))
+ return -EINVAL;
fmt_buffer = kzalloc(fmt_buffer_size, GFP_KERNEL | GFP_DMA);
if (!fmt_buffer)
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index d55862605b82..fd1bbe970755 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -330,7 +330,7 @@ static int dasd_ioctl_check_format(struct block_device *bdev, void __user *argp)
static int dasd_release_space(struct dasd_device *device,
struct format_data_t *rdata)
{
- if (!device->discipline->is_ese && !device->discipline->is_ese(device))
+ if (!device->discipline->is_ese || !device->discipline->is_ese(device))
return -ENOTSUPP;
if (!device->discipline->release_space)
return -ENOTSUPP;
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 357889cc03f0..2d3a766991a0 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -1048,7 +1048,7 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
if (rc)
goto out_free;
- if (perms != &ap_perms && domain < AUTOSEL_DOM) {
+ if (perms != &ap_perms && domain < AP_DOMAINS) {
if (ap_msg.flags & AP_MSG_FLAG_ADMIN) {
if (!test_bit_inv(domain, perms->adm)) {
rc = -ENODEV;
diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c
index 0c7172880dff..c3e3f3a3d8f9 100644
--- a/drivers/s390/crypto/zcrypt_ccamisc.c
+++ b/drivers/s390/crypto/zcrypt_ccamisc.c
@@ -1232,6 +1232,9 @@ int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey,
} __packed * prepparm;
int keytoklen = ((struct cipherkeytoken *)ckey)->len;
+ if (keytoklen > PARMBSIZE - sizeof(struct aureqparm))
+ return -EINVAL;
+
/* get already prepared memory for 2 cprbs with param block each */
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk);
if (rc)
@@ -1399,6 +1402,9 @@ int cca_ecc2protkey(u16 cardnr, u16 domain, const u8 *key,
} __packed * prepparm;
int keylen = ((struct eccprivkeytoken *)key)->len;
+ if (keylen > PARMBSIZE - sizeof(struct aureqparm))
+ return -EINVAL;
+
/* get already prepared memory for 2 cprbs with param block each */
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk);
if (rc)
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index f0f3b6272d5b..8f34d4eee012 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6526,6 +6526,9 @@ int qeth_siocdevprivate(struct net_device *dev, struct ifreq *rq, void __user *d
struct qeth_card *card = dev->ml_priv;
int rc = 0;
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
switch (cmd) {
case SIOC_QETH_ADP_SET_SNMP_CONTROL:
rc = qeth_snmp_command(card, data);
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index ab2f35bc294d..d3cc884ccd59 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -254,6 +254,7 @@ static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter)
{
mempool_destroy(adapter->pool.erp_req);
+ mempool_destroy(adapter->pool.gid_pn_req);
mempool_destroy(adapter->pool.scsi_req);
mempool_destroy(adapter->pool.scsi_abort);
mempool_destroy(adapter->pool.qtcb_pool);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 7075dde4584d..d386672d59e4 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -5345,15 +5345,7 @@ static int _resume_v3_hw(struct device *device)
return rc;
}
phys_init_v3_hw(hisi_hba);
-
- /*
- * If a directly-attached disk is removed during suspend, a deadlock
- * may occur, as the PHYE_RESUME_TIMEOUT processing will require the
- * hisi_hba->device to be active, which can only happen when resume
- * completes. So don't wait for the HA event workqueue to drain upon
- * resume.
- */
- sas_resume_ha_no_sync(sha);
+ sas_resume_ha(sha);
clear_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags);
dev_warn(dev, "end of resuming controller\n");
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 916c07648460..213aea93120d 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -918,7 +918,7 @@ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
}
senselen = get_unaligned_be16(data);
- if (datalen < senselen)
+ if (datalen < senselen + 2)
goto invalid_datalen;
memcpy(sc->sense_buffer, data + 2,
diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
index c182aa83f2c9..4d2320512943 100644
--- a/drivers/scsi/libiscsi_tcp.c
+++ b/drivers/scsi/libiscsi_tcp.c
@@ -763,13 +763,6 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
rc = __iscsi_complete_pdu(conn, hdr, NULL, 0);
spin_unlock(&conn->session->back_lock);
break;
- case ISCSI_OP_SCSI_CMD_RSP:
- if (tcp_conn->in.datalen) {
- iscsi_tcp_data_recv_prep(tcp_conn);
- return 0;
- }
- rc = iscsi_complete_pdu(conn, hdr, NULL, 0);
- break;
case ISCSI_OP_R2T:
if (ahslen) {
rc = ISCSI_ERR_AHSLEN;
@@ -777,6 +770,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
}
rc = iscsi_tcp_r2t_rsp(conn, hdr);
break;
+ case ISCSI_OP_SCSI_CMD_RSP:
case ISCSI_OP_LOGIN_RSP:
case ISCSI_OP_TEXT_RSP:
case ISCSI_OP_REJECT:
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 8586dc79f2a0..9fcdad2b55a8 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -409,7 +409,7 @@ static void sas_resume_insert_broadcast_ha(struct sas_ha_struct *ha)
}
}
-static void _sas_resume_ha(struct sas_ha_struct *ha, bool drain)
+void sas_resume_ha(struct sas_ha_struct *ha)
{
const unsigned long tmo = msecs_to_jiffies(25000);
int i;
@@ -425,6 +425,23 @@ static void _sas_resume_ha(struct sas_ha_struct *ha, bool drain)
dev_info(ha->dev, "waiting up to 25 seconds for %d phy%s to resume\n",
i, i > 1 ? "s" : "");
wait_event_timeout(ha->eh_wait_q, phys_suspended(ha) == 0, tmo);
+
+ /*
+ * All phys are back up or timed out. Turn on I/O and drain
+ * pending work.
+ */
+ scsi_unblock_requests(ha->shost);
+ sas_drain_work(ha);
+
+ /*
+ * Send PHYE_RESUME_TIMEOUT after sas_drain_work(). The handler
+ * calls sas_deform_port() -> sas_destruct_devices(), which removes
+ * SCSI devices and, for LLDDs using device_link() PM sync, waits
+ * for the host to be runtime-active. Sending it before the drain
+ * would deadlock: the drain waits for the handler, the handler
+ * waits for host resume, and host resume waits for the drain to
+ * finish.
+ */
for (i = 0; i < ha->num_phys; i++) {
struct asd_sas_phy *phy = ha->sas_phy[i];
@@ -435,12 +452,6 @@ static void _sas_resume_ha(struct sas_ha_struct *ha, bool drain)
}
}
- /* all phys are back up or timed out, turn on i/o so we can
- * flush out disks that did not return
- */
- scsi_unblock_requests(ha->shost);
- if (drain)
- sas_drain_work(ha);
clear_bit(SAS_HA_RESUMING, &ha->state);
sas_queue_deferred_work(ha);
@@ -449,20 +460,8 @@ static void _sas_resume_ha(struct sas_ha_struct *ha, bool drain)
*/
sas_resume_insert_broadcast_ha(ha);
}
-
-void sas_resume_ha(struct sas_ha_struct *ha)
-{
- _sas_resume_ha(ha, true);
-}
EXPORT_SYMBOL(sas_resume_ha);
-/* A no-sync variant, which does not call sas_drain_ha(). */
-void sas_resume_ha_no_sync(struct sas_ha_struct *ha)
-{
- _sas_resume_ha(ha, false);
-}
-EXPORT_SYMBOL(sas_resume_ha_no_sync);
-
void sas_suspend_ha(struct sas_ha_struct *ha)
{
int i;
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 841f92474678..573bb3fcecd5 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -4469,6 +4469,7 @@ static int resp_report_zones(struct scsi_cmnd *scp,
u32 alloc_len, rep_opts, rep_len;
bool partial;
u64 lba, zs_lba;
+ u64 arr_len;
u8 *arr = NULL, *desc;
u8 *cmd = scp->cmnd;
struct sdeb_zone_state *zsp = NULL;
@@ -4490,9 +4491,12 @@ static int resp_report_zones(struct scsi_cmnd *scp,
return check_condition_result;
}
- rep_max_zones = (alloc_len - 64) >> ilog2(RZONES_DESC_HD);
+ rep_max_zones = (ALIGN((u64)alloc_len, RZONES_DESC_HD) - RZONES_DESC_HD) >>
+ ilog2(RZONES_DESC_HD);
+ rep_max_zones = min_t(unsigned int, rep_max_zones, devip->nr_zones);
+ arr_len = (u64)RZONES_DESC_HD * (rep_max_zones + 1);
- arr = kzalloc(alloc_len, GFP_ATOMIC | __GFP_NOWARN);
+ arr = kzalloc(arr_len, GFP_ATOMIC | __GFP_NOWARN);
if (!arr) {
mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
INSUFF_RES_ASCQ);
diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
index 94e91835062b..b20214027fc2 100644
--- a/drivers/soc/qcom/ice.c
+++ b/drivers/soc/qcom/ice.c
@@ -48,6 +48,7 @@ struct qcom_ice {
struct device_link *link;
struct clk *core_clk;
+ struct clk *iface_clk;
};
static DEFINE_XARRAY(ice_handles);
@@ -149,8 +150,13 @@ int qcom_ice_resume(struct qcom_ice *ice)
err = clk_prepare_enable(ice->core_clk);
if (err) {
- dev_err(dev, "failed to enable core clock (%d)\n",
- err);
+ dev_err(dev, "Failed to enable core clock: %d\n", err);
+ return err;
+ }
+
+ err = clk_prepare_enable(ice->iface_clk);
+ if (err) {
+ dev_err(dev, "Failed to enable iface clock: %d\n", err);
return err;
}
@@ -160,6 +166,7 @@ EXPORT_SYMBOL_GPL(qcom_ice_resume);
int qcom_ice_suspend(struct qcom_ice *ice)
{
+ clk_disable_unprepare(ice->iface_clk);
clk_disable_unprepare(ice->core_clk);
return 0;
@@ -240,11 +247,17 @@ static struct qcom_ice *qcom_ice_create(struct device *dev,
engine->core_clk = devm_clk_get_optional_enabled(dev, "ice_core_clk");
if (!engine->core_clk)
engine->core_clk = devm_clk_get_optional_enabled(dev, "ice");
+ if (!engine->core_clk)
+ engine->core_clk = devm_clk_get_optional_enabled(dev, "core");
if (!engine->core_clk)
engine->core_clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(engine->core_clk))
return ERR_CAST(engine->core_clk);
+ engine->iface_clk = devm_clk_get_optional_enabled(dev, "iface");
+ if (IS_ERR(engine->iface_clk))
+ return ERR_CAST(engine->iface_clk);
+
if (!qcom_ice_check_supported(engine))
return ERR_PTR(-EOPNOTSUPP);
diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c
index c6579db42eff..63222eb61a02 100644
--- a/drivers/spi/spi-cadence.c
+++ b/drivers/spi/spi-cadence.c
@@ -108,6 +108,7 @@
* @rxbuf: Pointer to the RX buffer
* @tx_bytes: Number of bytes left to transfer
* @rx_bytes: Number of bytes requested
+ * @n_bytes: Number of bytes per word
* @dev_busy: Device busy flag
* @is_decoded_cs: Flag for decoder property set or not
* @tx_fifo_depth: Depth of the TX FIFO
@@ -118,15 +119,23 @@ struct cdns_spi {
struct clk *pclk;
unsigned int clk_rate;
u32 speed_hz;
- const u8 *txbuf;
- u8 *rxbuf;
+ const void *txbuf;
+ void *rxbuf;
int tx_bytes;
int rx_bytes;
+ u8 n_bytes;
u8 dev_busy;
u32 is_decoded_cs;
unsigned int tx_fifo_depth;
};
+enum cdns_spi_frame_n_bytes {
+ CDNS_SPI_N_BYTES_NULL = 0,
+ CDNS_SPI_N_BYTES_U8 = 1,
+ CDNS_SPI_N_BYTES_U16 = 2,
+ CDNS_SPI_N_BYTES_U32 = 4
+};
+
/* Macros for the SPI controller read/write */
static inline u32 cdns_spi_read(struct cdns_spi *xspi, u32 offset)
{
@@ -302,13 +311,87 @@ static int cdns_spi_setup_transfer(struct spi_device *spi,
return 0;
}
+static u8 cdns_spi_n_bytes(struct spi_transfer *transfer)
+{
+ if (transfer->bits_per_word <= 8)
+ return CDNS_SPI_N_BYTES_U8;
+ else if (transfer->bits_per_word <= 16)
+ return CDNS_SPI_N_BYTES_U16;
+ else
+ return CDNS_SPI_N_BYTES_U32;
+}
+
+static inline void cdns_spi_reader(struct cdns_spi *xspi)
+{
+ u32 rxw = 0;
+
+ if (xspi->rxbuf && !IS_ALIGNED((uintptr_t)xspi->rxbuf, xspi->n_bytes)) {
+ pr_err("%s: rxbuf address is not aligned for %d bytes\n",
+ __func__, xspi->n_bytes);
+ return;
+ }
+
+ rxw = cdns_spi_read(xspi, CDNS_SPI_RXD);
+ if (xspi->rxbuf) {
+ switch (xspi->n_bytes) {
+ case CDNS_SPI_N_BYTES_U8:
+ *(u8 *)xspi->rxbuf = rxw;
+ break;
+ case CDNS_SPI_N_BYTES_U16:
+ *(u16 *)xspi->rxbuf = rxw;
+ break;
+ case CDNS_SPI_N_BYTES_U32:
+ *(u32 *)xspi->rxbuf = rxw;
+ break;
+ default:
+ pr_err("%s invalid n_bytes %d\n", __func__,
+ xspi->n_bytes);
+ return;
+ }
+ xspi->rxbuf = (u8 *)xspi->rxbuf + xspi->n_bytes;
+ }
+}
+
+static inline void cdns_spi_writer(struct cdns_spi *xspi)
+{
+ u32 txw = 0;
+
+ if (xspi->txbuf && !IS_ALIGNED((uintptr_t)xspi->txbuf, xspi->n_bytes)) {
+ pr_err("%s: txbuf address is not aligned for %d bytes\n",
+ __func__, xspi->n_bytes);
+ return;
+ }
+
+ if (xspi->txbuf) {
+ switch (xspi->n_bytes) {
+ case CDNS_SPI_N_BYTES_U8:
+ txw = *(u8 *)xspi->txbuf;
+ break;
+ case CDNS_SPI_N_BYTES_U16:
+ txw = *(u16 *)xspi->txbuf;
+ break;
+ case CDNS_SPI_N_BYTES_U32:
+ txw = *(u32 *)xspi->txbuf;
+ break;
+ default:
+ pr_err("%s invalid n_bytes %d\n", __func__,
+ xspi->n_bytes);
+ return;
+ }
+ cdns_spi_write(xspi, CDNS_SPI_TXD, txw);
+ xspi->txbuf = (u8 *)xspi->txbuf + xspi->n_bytes;
+ }
+}
+
/**
* cdns_spi_process_fifo - Fills the TX FIFO, and drain the RX FIFO
+ * @ctlr: Pointer to the spi_controller structure
* @xspi: Pointer to the cdns_spi structure
* @ntx: Number of bytes to pack into the TX FIFO
* @nrx: Number of bytes to drain from the RX FIFO
*/
-static void cdns_spi_process_fifo(struct cdns_spi *xspi, int ntx, int nrx)
+static void cdns_spi_process_fifo(struct spi_controller *ctlr,
+ struct cdns_spi *xspi, int ntx, int nrx)
{
ntx = clamp(ntx, 0, xspi->tx_bytes);
nrx = clamp(nrx, 0, xspi->rx_bytes);
@@ -318,23 +401,24 @@ static void cdns_spi_process_fifo(struct cdns_spi *xspi, int ntx, int nrx)
while (ntx || nrx) {
if (nrx) {
- u8 data = cdns_spi_read(xspi, CDNS_SPI_RXD);
-
- if (xspi->rxbuf)
- *xspi->rxbuf++ = data;
-
+ cdns_spi_reader(xspi);
nrx--;
}
if (ntx) {
- if (xspi->txbuf)
- cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++);
- else
- cdns_spi_write(xspi, CDNS_SPI_TXD, 0);
+ /* When xspi in busy condition, bytes may send failed,
+ * then spi control didn't work thoroughly, add one byte
+ * delay. Only in host mode; in target mode this delay
+ * causes data corruption as the target fails to prepare
+ * data in time.
+ */
+ if (!spi_controller_is_target(ctlr) &&
+ (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_TXFULL))
+ udelay(10);
+ cdns_spi_writer(xspi);
ntx--;
}
-
}
}
@@ -385,14 +469,14 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id)
cdns_spi_write(xspi, CDNS_SPI_THLD, 1);
if (xspi->tx_bytes) {
- cdns_spi_process_fifo(xspi, trans_cnt, trans_cnt);
+ cdns_spi_process_fifo(ctlr, xspi, trans_cnt, trans_cnt);
} else {
/* Fixed delay due to controller limitation with
* RX_NEMPTY incorrect status
* Xilinx AR:65885 contains more details
*/
udelay(10);
- cdns_spi_process_fifo(xspi, 0, trans_cnt);
+ cdns_spi_process_fifo(ctlr, xspi, 0, trans_cnt);
cdns_spi_write(xspi, CDNS_SPI_IDR,
CDNS_SPI_IXR_DEFAULT);
spi_finalize_current_transfer(ctlr);
@@ -445,13 +529,11 @@ static int cdns_transfer_one(struct spi_controller *ctlr,
cdns_spi_write(xspi, CDNS_SPI_THLD, xspi->tx_fifo_depth >> 1);
}
- /* When xspi in busy condition, bytes may send failed,
- * then spi control didn't work thoroughly, add one byte delay
- */
- if (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_TXFULL)
- udelay(10);
+ xspi->n_bytes = cdns_spi_n_bytes(transfer);
+ xspi->tx_bytes = DIV_ROUND_UP(xspi->tx_bytes, xspi->n_bytes);
+ xspi->rx_bytes = DIV_ROUND_UP(xspi->rx_bytes, xspi->n_bytes);
- cdns_spi_process_fifo(xspi, xspi->tx_fifo_depth, 0);
+ cdns_spi_process_fifo(ctlr, xspi, xspi->tx_fifo_depth, 0);
cdns_spi_write(xspi, CDNS_SPI_IER, CDNS_SPI_IXR_DEFAULT);
return transfer->len;
@@ -640,6 +722,10 @@ static int cdns_spi_probe(struct platform_device *pdev)
ctlr->unprepare_transfer_hardware = cdns_unprepare_transfer_hardware;
ctlr->mode_bits = SPI_CPOL | SPI_CPHA;
ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
+ ctlr->flags = SPI_CONTROLLER_MUST_TX;
+
+ if (of_device_is_compatible(pdev->dev.of_node, "cix,sky1-spi-r1p6"))
+ ctlr->bits_per_word_mask |= SPI_BPW_MASK(16) | SPI_BPW_MASK(32);
if (!spi_controller_is_target(ctlr)) {
ctlr->mode_bits |= SPI_CS_HIGH;
@@ -796,6 +882,7 @@ static const struct dev_pm_ops cdns_spi_dev_pm_ops = {
static const struct of_device_id cdns_spi_of_match[] = {
{ .compatible = "xlnx,zynq-spi-r1p6" },
+ { .compatible = "cix,sky1-spi-r1p6" },
{ .compatible = "cdns,spi-r1p6" },
{ /* end of table */ }
};
diff --git a/drivers/spi/spi-qcom-qspi.c b/drivers/spi/spi-qcom-qspi.c
index 49b775134485..591fdd2ec7b8 100644
--- a/drivers/spi/spi-qcom-qspi.c
+++ b/drivers/spi/spi-qcom-qspi.c
@@ -759,7 +759,8 @@ static int qcom_qspi_probe(struct platform_device *pdev)
return dev_err_probe(dev, ret, "could not set DMA mask\n");
host->max_speed_hz = 300000000;
- host->max_dma_len = 65536; /* as per HPG */
+ /* as per HPG, it is 64KB, limit to 60KB to avoid boundary condition failures */
+ host->max_dma_len = 0xf000;
host->dma_alignment = QSPI_ALIGN_REQ;
host->num_chipselect = QSPI_NUM_CS;
host->bus_num = -1;
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index a6a06a5f7483..4d025163569a 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -885,7 +885,7 @@ static sense_reason_t iblock_execute_pr_out(struct se_cmd *cmd, u8 sa, u64 key,
break;
case PRO_PREEMPT:
case PRO_PREEMPT_AND_ABORT:
- if (!ops->pr_clear) {
+ if (!ops->pr_preempt) {
pr_err("block_device does not support pr_preempt.\n");
return TCM_UNSUPPORTED_SCSI_OPCODE;
}
@@ -895,8 +895,8 @@ static sense_reason_t iblock_execute_pr_out(struct se_cmd *cmd, u8 sa, u64 key,
sa == PRO_PREEMPT_AND_ABORT);
break;
case PRO_RELEASE:
- if (!ops->pr_clear) {
- pr_err("block_device does not support pr_pclear.\n");
+ if (!ops->pr_release) {
+ pr_err("block_device does not support pr_release.\n");
return TCM_UNSUPPORTED_SCSI_OPCODE;
}
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index b9a144a59dff..f4e3ba173dbe 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1670,6 +1670,7 @@ int target_init_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
u32 data_length, int task_attr, int data_dir, int flags)
{
struct se_portal_group *se_tpg;
+ int ret;
se_tpg = se_sess->se_tpg;
BUG_ON(!se_tpg);
@@ -1699,7 +1700,11 @@ int target_init_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
* necessary for fabrics using TARGET_SCF_ACK_KREF that expect a second
* kref_put() to happen during fabric packet acknowledgement.
*/
- return target_get_sess_cmd(se_cmd, flags & TARGET_SCF_ACK_KREF);
+ ret = target_get_sess_cmd(se_cmd, flags & TARGET_SCF_ACK_KREF);
+ if (ret)
+ se_cmd->cmd_cnt = NULL;
+
+ return ret;
}
EXPORT_SYMBOL_GPL(target_init_cmd);
@@ -1994,8 +1999,10 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
* allocation failure.
*/
ret = core_tmr_alloc_req(se_cmd, fabric_tmr_ptr, tm_type, gfp);
- if (ret < 0)
+ if (ret < 0) {
+ se_cmd->cmd_cnt = NULL;
return -ENOMEM;
+ }
if (tm_type == TMR_ABORT_TASK)
se_cmd->se_tmr_req->ref_task_tag = tag;
@@ -2003,6 +2010,7 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
/* See target_submit_cmd for commentary */
ret = target_get_sess_cmd(se_cmd, flags & TARGET_SCF_ACK_KREF);
if (ret) {
+ se_cmd->cmd_cnt = NULL;
core_tmr_release_req(se_cmd->se_tmr_req);
return ret;
}
diff --git a/drivers/thunderbolt/xdomain.c b/drivers/thunderbolt/xdomain.c
index a5ec70327d81..87fbced665b9 100644
--- a/drivers/thunderbolt/xdomain.c
+++ b/drivers/thunderbolt/xdomain.c
@@ -783,9 +783,13 @@ static void tb_xdp_handle_request(struct work_struct *work)
* the xdomain related to this connection as well in
* case there is a change in services it offers.
*/
- if (xd && device_is_registered(&xd->dev))
- queue_delayed_work(tb->wq, &xd->state_work,
- msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT));
+ if (xd) {
+ mutex_lock(&xd->lock);
+ if (!xd->removing && device_is_registered(&xd->dev))
+ queue_delayed_work(tb->wq, &xd->state_work,
+ msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT));
+ mutex_unlock(&xd->lock);
+ }
break;
case UUID_REQUEST_OLD:
@@ -798,8 +802,12 @@ static void tb_xdp_handle_request(struct work_struct *work)
* received UUID request from the remote host.
*/
if (!ret && xd && xd->state == XDOMAIN_STATE_ERROR) {
- dev_dbg(&xd->dev, "restarting handshake\n");
- start_handshake(xd);
+ mutex_lock(&xd->lock);
+ if (!xd->removing) {
+ dev_dbg(&xd->dev, "restarting handshake\n");
+ start_handshake(xd);
+ }
+ mutex_unlock(&xd->lock);
}
break;
@@ -827,9 +835,13 @@ static void tb_xdp_handle_request(struct work_struct *work)
ret = tb_xdp_link_state_change_response(ctl, route,
sequence, 0);
- xd->target_link_width = lsc->tlw;
- queue_delayed_work(tb->wq, &xd->state_work,
- msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT));
+ mutex_lock(&xd->lock);
+ if (!xd->removing) {
+ xd->target_link_width = lsc->tlw;
+ queue_delayed_work(tb->wq, &xd->state_work,
+ msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT));
+ }
+ mutex_unlock(&xd->lock);
} else {
tb_xdp_error_response(ctl, route, sequence,
ERROR_NOT_READY);
@@ -2018,6 +2030,10 @@ void tb_xdomain_remove(struct tb_xdomain *xd)
{
tb_xdomain_debugfs_remove(xd);
+ mutex_lock(&xd->lock);
+ xd->removing = true;
+ mutex_unlock(&xd->lock);
+
stop_handshake(xd);
device_for_each_child_reverse(&xd->dev, xd, unregister_service);
@@ -2412,8 +2428,12 @@ static int update_xdomain(struct device *dev, void *data)
xd = tb_to_xdomain(dev);
if (xd) {
- queue_delayed_work(xd->tb->wq, &xd->properties_changed_work,
- msecs_to_jiffies(50));
+ mutex_lock(&xd->lock);
+ if (!xd->removing)
+ queue_delayed_work(xd->tb->wq,
+ &xd->properties_changed_work,
+ msecs_to_jiffies(50));
+ mutex_unlock(&xd->lock);
}
return 0;
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 142abff30122..3bbe1088b7e4 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -9830,6 +9830,7 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
req_link_state == UIC_LINK_ACTIVE_STATE) {
ufshcd_disable_auto_bkops(hba);
flush_work(&hba->eeh_work);
+ cancel_delayed_work_sync(&hba->ufs_rtc_update_work);
goto vops_suspend;
}
@@ -10039,10 +10040,11 @@ static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
if (ret)
goto set_old_link_state;
ufshcd_set_timestamp_attr(hba);
- schedule_delayed_work(&hba->ufs_rtc_update_work,
- msecs_to_jiffies(UFS_RTC_UPDATE_INTERVAL_MS));
}
+ schedule_delayed_work(&hba->ufs_rtc_update_work,
+ msecs_to_jiffies(UFS_RTC_UPDATE_INTERVAL_MS));
+
if (ufshcd_keep_autobkops_enabled_except_suspend(hba))
ufshcd_enable_auto_bkops(hba);
else
diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c
index 3811b7abaf58..d1f0735f6fd6 100644
--- a/drivers/usb/gadget/function/f_tcm.c
+++ b/drivers/usb/gadget/function/f_tcm.c
@@ -2011,31 +2011,158 @@ static int tcm_bind(struct usb_configuration *c, struct usb_function *f)
return -ENOTSUPP;
}
-struct guas_setup_wq {
- struct work_struct work;
- struct f_uas *fu;
- unsigned int alt;
-};
+static void tcm_cleanup_old_alt(struct f_uas *fu)
+{
+ if (fu->flags & USBG_IS_UAS)
+ uasp_cleanup_old_alt(fu);
+ else if (fu->flags & USBG_IS_BOT)
+ bot_cleanup_old_alt(fu);
+ fu->flags = 0;
+}
+
+static void tcm_delayed_set_alt_done(struct f_uas *fu)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
+ fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_IDLE;
+ fu->delayed_set_alt_cancel = false;
+ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
+}
+
+static bool tcm_delayed_set_alt_cancelled(struct f_uas *fu)
+{
+ bool cancelled;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
+ cancelled = fu->delayed_set_alt_cancel;
+ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
+
+ return cancelled;
+}
+
+static bool tcm_complete_delayed_status(struct f_uas *fu)
+{
+ struct usb_composite_dev *cdev = fu->function.config->cdev;
+ struct usb_request *req = cdev->req;
+ unsigned long cdev_flags;
+ bool cancelled;
+ int ret;
+
+ spin_lock_irqsave(&cdev->lock, cdev_flags);
+ spin_lock(&fu->delayed_set_alt_lock);
+ cancelled = fu->delayed_set_alt_cancel;
+ if (!cancelled) {
+ fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_IDLE;
+ fu->delayed_set_alt_cancel = false;
+ }
+ spin_unlock(&fu->delayed_set_alt_lock);
+
+ if (cancelled) {
+ spin_unlock_irqrestore(&cdev->lock, cdev_flags);
+ return false;
+ }
+
+ if (cdev->delayed_status == 0) {
+ WARN(cdev, "%s: Unexpected call\n", __func__);
+ } else if (--cdev->delayed_status == 0) {
+ req->length = 0;
+ req->context = cdev;
+ ret = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+ if (ret == 0) {
+ cdev->setup_pending = true;
+ } else {
+ req->status = 0;
+ req->complete(cdev->gadget->ep0, req);
+ }
+ }
+
+ spin_unlock_irqrestore(&cdev->lock, cdev_flags);
+
+ return true;
+}
+
+static bool tcm_cancel_delayed_set_alt(struct f_uas *fu)
+{
+ bool cleanup = false;
+ bool cancel = false;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
+ switch (fu->delayed_set_alt_state) {
+ case USBG_DELAYED_SET_ALT_IDLE:
+ cleanup = true;
+ break;
+ case USBG_DELAYED_SET_ALT_QUEUED:
+ case USBG_DELAYED_SET_ALT_RUNNING:
+ fu->delayed_set_alt_cancel = true;
+ cancel = true;
+ break;
+ }
+ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
+
+ if (cancel && cancel_work(&fu->delayed_set_alt)) {
+ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
+ if (fu->delayed_set_alt_state == USBG_DELAYED_SET_ALT_QUEUED) {
+ fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_IDLE;
+ fu->delayed_set_alt_cancel = false;
+ cleanup = true;
+ }
+ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
+ }
+
+ return cleanup;
+}
+
+static void tcm_cancel_delayed_set_alt_sync(struct f_uas *fu)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
+ if (fu->delayed_set_alt_state != USBG_DELAYED_SET_ALT_IDLE)
+ fu->delayed_set_alt_cancel = true;
+ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
+
+ cancel_work_sync(&fu->delayed_set_alt);
+
+ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
+ fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_IDLE;
+ fu->delayed_set_alt_cancel = false;
+ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
+}
static void tcm_delayed_set_alt(struct work_struct *wq)
{
- struct guas_setup_wq *work = container_of(wq, struct guas_setup_wq,
- work);
- struct f_uas *fu = work->fu;
- int alt = work->alt;
+ struct f_uas *fu = container_of(wq, struct f_uas, delayed_set_alt);
+ unsigned long flags;
+ unsigned int alt;
- kfree(work);
+ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
+ if (fu->delayed_set_alt_state != USBG_DELAYED_SET_ALT_QUEUED) {
+ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
+ return;
+ }
+ fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_RUNNING;
+ alt = fu->delayed_alt;
+ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
- if (fu->flags & USBG_IS_BOT)
- bot_cleanup_old_alt(fu);
- if (fu->flags & USBG_IS_UAS)
- uasp_cleanup_old_alt(fu);
+ tcm_cleanup_old_alt(fu);
+
+ if (tcm_delayed_set_alt_cancelled(fu))
+ goto out_done;
if (alt == USB_G_ALT_INT_BBB)
bot_set_alt(fu);
else if (alt == USB_G_ALT_INT_UAS)
uasp_set_alt(fu);
- usb_composite_setup_continue(fu->function.config->cdev);
+
+ if (tcm_complete_delayed_status(fu))
+ return;
+
+ tcm_cleanup_old_alt(fu);
+out_done:
+ tcm_delayed_set_alt_done(fu);
}
static int tcm_get_alt(struct usb_function *f, unsigned intf)
@@ -2061,15 +2188,20 @@ static int tcm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
return -EOPNOTSUPP;
if ((alt == USB_G_ALT_INT_BBB) || (alt == USB_G_ALT_INT_UAS)) {
- struct guas_setup_wq *work;
+ unsigned long flags;
- work = kmalloc(sizeof(*work), GFP_ATOMIC);
- if (!work)
- return -ENOMEM;
- INIT_WORK(&work->work, tcm_delayed_set_alt);
- work->fu = fu;
- work->alt = alt;
- schedule_work(&work->work);
+ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
+ if (fu->delayed_set_alt_state != USBG_DELAYED_SET_ALT_IDLE) {
+ spin_unlock_irqrestore(&fu->delayed_set_alt_lock,
+ flags);
+ return -EBUSY;
+ }
+ fu->delayed_alt = alt;
+ fu->delayed_set_alt_cancel = false;
+ fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_QUEUED;
+ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
+
+ schedule_work(&fu->delayed_set_alt);
return USB_GADGET_DELAYED_STATUS;
}
return -EOPNOTSUPP;
@@ -2079,11 +2211,8 @@ static void tcm_disable(struct usb_function *f)
{
struct f_uas *fu = to_f_uas(f);
- if (fu->flags & USBG_IS_UAS)
- uasp_cleanup_old_alt(fu);
- else if (fu->flags & USBG_IS_BOT)
- bot_cleanup_old_alt(fu);
- fu->flags = 0;
+ if (tcm_cancel_delayed_set_alt(fu))
+ tcm_cleanup_old_alt(fu);
}
static int tcm_setup(struct usb_function *f,
@@ -2231,11 +2360,16 @@ static void tcm_free(struct usb_function *f)
{
struct f_uas *tcm = to_f_uas(f);
+ tcm_cancel_delayed_set_alt_sync(tcm);
kfree(tcm);
}
static void tcm_unbind(struct usb_configuration *c, struct usb_function *f)
{
+ struct f_uas *fu = to_f_uas(f);
+
+ tcm_cancel_delayed_set_alt_sync(fu);
+ tcm_cleanup_old_alt(fu);
usb_free_all_descriptors(f);
}
@@ -2268,6 +2402,8 @@ static struct usb_function *tcm_alloc(struct usb_function_instance *fi)
fu->function.disable = tcm_disable;
fu->function.free_func = tcm_free;
fu->tpg = tpg_instances[i].tpg;
+ INIT_WORK(&fu->delayed_set_alt, tcm_delayed_set_alt);
+ spin_lock_init(&fu->delayed_set_alt_lock);
mutex_unlock(&tpg_instances_lock);
return &fu->function;
diff --git a/drivers/usb/gadget/function/tcm.h b/drivers/usb/gadget/function/tcm.h
index 3cd565794ad7..6c9bdbeed3c8 100644
--- a/drivers/usb/gadget/function/tcm.h
+++ b/drivers/usb/gadget/function/tcm.h
@@ -3,6 +3,7 @@
#define __TARGET_USB_GADGET_H__
#include <linux/kref.h>
+#include <linux/spinlock.h>
/* #include <linux/usb/uas.h> */
#include <linux/usb/composite.h>
#include <linux/usb/uas.h>
@@ -26,6 +27,12 @@ enum {
#define USB_G_DEFAULT_SESSION_TAGS 128
+enum {
+ USBG_DELAYED_SET_ALT_IDLE = 0,
+ USBG_DELAYED_SET_ALT_QUEUED,
+ USBG_DELAYED_SET_ALT_RUNNING,
+};
+
struct tcm_usbg_nexus {
struct se_session *tvn_se_sess;
};
@@ -117,6 +124,12 @@ struct f_uas {
#define USBG_IS_BOT (1 << 3)
#define USBG_BOT_CMD_PEND (1 << 4)
+ struct work_struct delayed_set_alt;
+ spinlock_t delayed_set_alt_lock; /* protects delayed_set_alt_* */
+ unsigned int delayed_alt;
+ unsigned int delayed_set_alt_state;
+ bool delayed_set_alt_cancel;
+
struct usbg_cdb cmd;
struct usb_ep *ep_in;
struct usb_ep *ep_out;
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 22d91f9f138e..d79169d37b72 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -318,13 +318,11 @@ static int omap2430_probe(struct platform_device *pdev)
glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
if (!glue)
- goto err0;
+ return -ENOMEM;
musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
- if (!musb) {
- dev_err(&pdev->dev, "failed to allocate musb device\n");
- goto err0;
- }
+ if (!musb)
+ return -ENOMEM;
musb->dev.parent = &pdev->dev;
musb->dev.dma_mask = &omap2430_dmamask;
@@ -348,15 +346,15 @@ static int omap2430_probe(struct platform_device *pdev)
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
- goto err2;
+ goto err_put_musb;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
- goto err2;
+ goto err_put_musb;
config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
if (!config)
- goto err2;
+ goto err_put_musb;
of_property_read_u32(np, "mode", (u32 *)&pdata->mode);
of_property_read_u32(np, "interface-type",
@@ -379,7 +377,7 @@ static int omap2430_probe(struct platform_device *pdev)
if (!control_pdev) {
dev_err(&pdev->dev, "Failed to get control device\n");
ret = -EINVAL;
- goto err2;
+ goto err_put_musb;
}
glue->control_otghs = &control_pdev->dev;
}
@@ -455,22 +453,19 @@ static int omap2430_probe(struct platform_device *pdev)
ret = platform_device_add(musb);
if (ret) {
dev_err(&pdev->dev, "failed to register musb device\n");
- goto err3;
+ goto err_disable_rpm;
}
- of_node_put(np);
return 0;
-err3:
+err_disable_rpm:
pm_runtime_disable(glue->dev);
err_put_control_otghs:
if (!IS_ERR(glue->control_otghs))
put_device(glue->control_otghs);
-err2:
- of_node_put(np);
+err_put_musb:
platform_device_put(musb);
-err0:
return ret;
}
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index a70e0118680c..b0d5f071664f 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -1231,6 +1231,7 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
INIT_WORK(&con->work, ucsi_handle_connector_change);
init_completion(&con->complete);
mutex_init(&con->lock);
+ lockdep_set_class(&con->lock, &con->lock_key);
INIT_LIST_HEAD(&con->partner_tasks);
con->ucsi = ucsi;
@@ -1406,6 +1407,63 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
return ret;
}
+static void ucsi_unregister_port(struct ucsi_connector *con)
+{
+ struct ucsi_work *uwork;
+
+ if (con->wq) {
+ mutex_lock(&con->lock);
+ ucsi_unregister_partner(con);
+ /*
+ * queue delayed items immediately so they can execute
+ * and free themselves before the wq is destroyed
+ */
+ list_for_each_entry(uwork, &con->partner_tasks, node) {
+ if (cancel_delayed_work(&uwork->work))
+ queue_delayed_work(con->wq, &uwork->work, 0);
+ }
+ mutex_unlock(&con->lock);
+
+ destroy_workqueue(con->wq);
+ con->wq = NULL;
+ } else {
+ ucsi_unregister_partner(con);
+ }
+
+ ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON);
+ ucsi_unregister_port_psy(con);
+
+ usb_power_delivery_unregister_capabilities(con->port_sink_caps);
+ con->port_sink_caps = NULL;
+ usb_power_delivery_unregister_capabilities(con->port_source_caps);
+ con->port_source_caps = NULL;
+ usb_power_delivery_unregister(con->pd);
+ con->pd = NULL;
+ typec_unregister_port(con->port);
+ con->port = NULL;
+}
+
+static u64 ucsi_get_supported_notifications(struct ucsi *ucsi)
+{
+ u8 features = ucsi->cap.features;
+ u64 ntfy = UCSI_ENABLE_NTFY_ALL;
+
+ if (!(features & UCSI_CAP_ALT_MODE_DETAILS))
+ ntfy &= ~UCSI_ENABLE_NTFY_CAM_CHANGE;
+
+ if (!(features & UCSI_CAP_PDO_DETAILS))
+ ntfy &= ~(UCSI_ENABLE_NTFY_PWR_LEVEL_CHANGE |
+ UCSI_ENABLE_NTFY_CAP_CHANGE);
+
+ if (!(features & UCSI_CAP_EXT_SUPPLY_NOTIFICATIONS))
+ ntfy &= ~UCSI_ENABLE_NTFY_EXT_PWR_SRC_CHANGE;
+
+ if (!(features & UCSI_CAP_PD_RESET))
+ ntfy &= ~UCSI_ENABLE_NTFY_PD_RESET_COMPLETE;
+
+ return ntfy;
+}
+
/**
* ucsi_init - Initialize UCSI interface
* @ucsi: UCSI to be initialized
@@ -1458,6 +1516,9 @@ static int ucsi_init(struct ucsi *ucsi)
goto err_reset;
}
+ for (i = 0; i < ucsi->cap.num_connectors; i++)
+ lockdep_register_key(&connector[i].lock_key);
+
/* Register all connectors */
for (i = 0; i < ucsi->cap.num_connectors; i++) {
connector[i].num = i + 1;
@@ -1466,8 +1527,8 @@ static int ucsi_init(struct ucsi *ucsi)
goto err_unregister;
}
- /* Enable all notifications */
- ntfy = UCSI_ENABLE_NTFY_ALL;
+ /* Enable all supported notifications */
+ ntfy = ucsi_get_supported_notifications(ucsi);
command = UCSI_SET_NOTIFICATION_ENABLE | ntfy;
ret = ucsi_send_command(ucsi, command, NULL, 0);
if (ret < 0)
@@ -1487,22 +1548,11 @@ static int ucsi_init(struct ucsi *ucsi)
return 0;
err_unregister:
- for (con = connector; con->port; con++) {
- if (con->wq)
- destroy_workqueue(con->wq);
- ucsi_unregister_partner(con);
- ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON);
- ucsi_unregister_port_psy(con);
-
- usb_power_delivery_unregister_capabilities(con->port_sink_caps);
- con->port_sink_caps = NULL;
- usb_power_delivery_unregister_capabilities(con->port_source_caps);
- con->port_source_caps = NULL;
- usb_power_delivery_unregister(con->pd);
- con->pd = NULL;
- typec_unregister_port(con->port);
- con->port = NULL;
- }
+ for (con = connector; con->port; con++)
+ ucsi_unregister_port(con);
+ for (i = 0; i < ucsi->cap.num_connectors; i++)
+ lockdep_unregister_key(&connector[i].lock_key);
+
kfree(connector);
err_reset:
memset(&ucsi->cap, 0, sizeof(ucsi->cap));
@@ -1728,33 +1778,8 @@ void ucsi_unregister(struct ucsi *ucsi)
for (i = 0; i < ucsi->cap.num_connectors; i++) {
cancel_work_sync(&ucsi->connector[i].work);
-
- if (ucsi->connector[i].wq) {
- struct ucsi_work *uwork;
-
- mutex_lock(&ucsi->connector[i].lock);
- /*
- * queue delayed items immediately so they can execute
- * and free themselves before the wq is destroyed
- */
- list_for_each_entry(uwork, &ucsi->connector[i].partner_tasks, node)
- mod_delayed_work(ucsi->connector[i].wq, &uwork->work, 0);
- mutex_unlock(&ucsi->connector[i].lock);
- destroy_workqueue(ucsi->connector[i].wq);
- }
-
- ucsi_unregister_partner(&ucsi->connector[i]);
- ucsi_unregister_altmodes(&ucsi->connector[i],
- UCSI_RECIPIENT_CON);
- ucsi_unregister_port_psy(&ucsi->connector[i]);
-
- usb_power_delivery_unregister_capabilities(ucsi->connector[i].port_sink_caps);
- ucsi->connector[i].port_sink_caps = NULL;
- usb_power_delivery_unregister_capabilities(ucsi->connector[i].port_source_caps);
- ucsi->connector[i].port_source_caps = NULL;
- usb_power_delivery_unregister(ucsi->connector[i].pd);
- ucsi->connector[i].pd = NULL;
- typec_unregister_port(ucsi->connector[i].port);
+ ucsi_unregister_port(&ucsi->connector[i]);
+ lockdep_unregister_key(&ucsi->connector[i].lock_key);
}
kfree(ucsi->connector);
diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
index 2cb34913358d..9ac5ad87f401 100644
--- a/drivers/usb/typec/ucsi/ucsi.h
+++ b/drivers/usb/typec/ucsi/ucsi.h
@@ -350,6 +350,7 @@ struct ucsi_connector {
struct ucsi *ucsi;
struct mutex lock; /* port lock */
+ struct lock_class_key lock_key;
struct work_struct work;
struct completion complete;
struct workqueue_struct *wq;
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index e4dfcf11b5f7..3b96c7ca7cfc 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -347,6 +347,10 @@ static Node *create_entry(const char __user *buffer, size_t count)
pr_debug("register: delim: %#x {%c}\n", del, del);
+ /* A flag-char delimiter runs the flag scan off the buffer. */
+ if (del == 'P' || del == 'O' || del == 'C' || del == 'F')
+ goto einval;
+
/* Pad the buffer with the delim to simplify parsing below. */
memset(buf + count, del, 8);
diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
index dabbfc3b7d77..9962ae292b12 100644
--- a/fs/btrfs/zoned.c
+++ b/fs/btrfs/zoned.c
@@ -1775,7 +1775,11 @@ static bool check_bg_is_active(struct btrfs_eb_write_context *ctx,
if (fs_info->treelog_bg == block_group->start) {
if (!btrfs_zone_activate(block_group)) {
- int ret_fin = btrfs_zone_finish_one_bg(fs_info);
+ int ret_fin;
+
+ btrfs_zoned_meta_io_unlock(fs_info);
+ ret_fin = btrfs_zone_finish_one_bg(fs_info);
+ btrfs_zoned_meta_io_lock(fs_info);
if (ret_fin != 1 || !btrfs_zone_activate(block_group))
return false;
diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c
index c53a1d220622..e95841961397 100644
--- a/fs/ceph/acl.c
+++ b/fs/ceph/acl.c
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include "super.h"
+#include "mds_client.h"
static inline void ceph_set_cached_acl(struct inode *inode,
int type, struct posix_acl *acl)
@@ -31,6 +32,7 @@ static inline void ceph_set_cached_acl(struct inode *inode,
struct posix_acl *ceph_get_acl(struct inode *inode, int type, bool rcu)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
int size;
unsigned int retry_cnt = 0;
const char *name;
@@ -72,8 +74,8 @@ struct posix_acl *ceph_get_acl(struct inode *inode, int type, bool rcu)
} else if (size == -ENODATA || size == 0) {
acl = NULL;
} else {
- pr_err_ratelimited("get acl %llx.%llx failed, err=%d\n",
- ceph_vinop(inode), size);
+ pr_err_ratelimited_client(cl, "%llx.%llx failed, err=%d\n",
+ ceph_vinop(inode), size);
acl = ERR_PTR(-EIO);
}
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index db4d11604e9d..6e0f8c1a8447 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -79,18 +79,18 @@ static inline struct ceph_snap_context *page_snap_context(struct page *page)
*/
static bool ceph_dirty_folio(struct address_space *mapping, struct folio *folio)
{
- struct inode *inode;
+ struct inode *inode = mapping->host;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci;
struct ceph_snap_context *snapc;
if (folio_test_dirty(folio)) {
- dout("%p dirty_folio %p idx %lu -- already dirty\n",
- mapping->host, folio, folio->index);
+ doutc(cl, "%llx.%llx %p idx %lu -- already dirty\n",
+ ceph_vinop(inode), folio, folio->index);
VM_BUG_ON_FOLIO(!folio_test_private(folio), folio);
return false;
}
- inode = mapping->host;
ci = ceph_inode(inode);
/* dirty the head */
@@ -110,12 +110,12 @@ static bool ceph_dirty_folio(struct address_space *mapping, struct folio *folio)
if (ci->i_wrbuffer_ref == 0)
ihold(inode);
++ci->i_wrbuffer_ref;
- dout("%p dirty_folio %p idx %lu head %d/%d -> %d/%d "
- "snapc %p seq %lld (%d snaps)\n",
- mapping->host, folio, folio->index,
- ci->i_wrbuffer_ref-1, ci->i_wrbuffer_ref_head-1,
- ci->i_wrbuffer_ref, ci->i_wrbuffer_ref_head,
- snapc, snapc->seq, snapc->num_snaps);
+ doutc(cl, "%llx.%llx %p idx %lu head %d/%d -> %d/%d "
+ "snapc %p seq %lld (%d snaps)\n",
+ ceph_vinop(inode), folio, folio->index,
+ ci->i_wrbuffer_ref-1, ci->i_wrbuffer_ref_head-1,
+ ci->i_wrbuffer_ref, ci->i_wrbuffer_ref_head,
+ snapc, snapc->seq, snapc->num_snaps);
spin_unlock(&ci->i_ceph_lock);
/*
@@ -136,23 +136,22 @@ static bool ceph_dirty_folio(struct address_space *mapping, struct folio *folio)
static void ceph_invalidate_folio(struct folio *folio, size_t offset,
size_t length)
{
- struct inode *inode;
- struct ceph_inode_info *ci;
+ struct inode *inode = folio->mapping->host;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
+ struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_snap_context *snapc;
- inode = folio->mapping->host;
- ci = ceph_inode(inode);
if (offset != 0 || length != folio_size(folio)) {
- dout("%p invalidate_folio idx %lu partial dirty page %zu~%zu\n",
- inode, folio->index, offset, length);
+ doutc(cl, "%llx.%llx idx %lu partial dirty page %zu~%zu\n",
+ ceph_vinop(inode), folio->index, offset, length);
return;
}
WARN_ON(!folio_test_locked(folio));
if (folio_test_private(folio)) {
- dout("%p invalidate_folio idx %lu full dirty page\n",
- inode, folio->index);
+ doutc(cl, "%llx.%llx idx %lu full dirty page\n",
+ ceph_vinop(inode), folio->index);
snapc = folio_detach_private(folio);
ceph_put_wrbuffer_cap_refs(ci, 1, snapc);
@@ -165,10 +164,10 @@ static void ceph_invalidate_folio(struct folio *folio, size_t offset,
static bool ceph_release_folio(struct folio *folio, gfp_t gfp)
{
struct inode *inode = folio->mapping->host;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
- dout("%llx:%llx release_folio idx %lu (%sdirty)\n",
- ceph_vinop(inode),
- folio->index, folio_test_dirty(folio) ? "" : "not ");
+ doutc(cl, "%llx.%llx idx %lu (%sdirty)\n", ceph_vinop(inode),
+ folio->index, folio_test_dirty(folio) ? "" : "not ");
if (folio_test_private(folio))
return false;
@@ -244,6 +243,7 @@ static void finish_netfs_read(struct ceph_osd_request *req)
{
struct inode *inode = req->r_inode;
struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
+ struct ceph_client *cl = fsc->client;
struct ceph_osd_data *osd_data = osd_req_op_extent_osd_data(req, 0);
struct netfs_io_subrequest *subreq = req->r_priv;
struct ceph_osd_req_op *op = &req->r_ops[0];
@@ -253,8 +253,8 @@ static void finish_netfs_read(struct ceph_osd_request *req)
ceph_update_read_metrics(&fsc->mdsc->metric, req->r_start_latency,
req->r_end_latency, osd_data->length, err);
- dout("%s: result %d subreq->len=%zu i_size=%lld\n", __func__, req->r_result,
- subreq->len, i_size_read(req->r_inode));
+ doutc(cl, "result %d subreq->len=%zu i_size=%lld\n", req->r_result,
+ subreq->len, i_size_read(req->r_inode));
/* no object means success but no data */
if (err == -ENOENT)
@@ -348,6 +348,7 @@ static void ceph_netfs_issue_read(struct netfs_io_subrequest *subreq)
struct inode *inode = rreq->inode;
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
+ struct ceph_client *cl = fsc->client;
struct ceph_osd_request *req = NULL;
struct ceph_vino vino = ceph_vino(inode);
struct iov_iter iter;
@@ -384,7 +385,8 @@ static void ceph_netfs_issue_read(struct netfs_io_subrequest *subreq)
goto out;
}
- dout("%s: pos=%llu orig_len=%zu len=%llu\n", __func__, subreq->start, subreq->len, len);
+ doutc(cl, "%llx.%llx pos=%llu orig_len=%zu len=%llu\n",
+ ceph_vinop(inode), subreq->start, subreq->len, len);
iov_iter_xarray(&iter, ITER_DEST, &rreq->mapping->i_pages, subreq->start, len);
@@ -401,8 +403,8 @@ static void ceph_netfs_issue_read(struct netfs_io_subrequest *subreq)
err = iov_iter_get_pages_alloc2(&iter, &pages, len, &page_off);
if (err < 0) {
- dout("%s: iov_ter_get_pages_alloc returned %d\n",
- __func__, err);
+ doutc(cl, "%llx.%llx failed to allocate pages, %d\n",
+ ceph_vinop(inode), err);
goto out;
}
@@ -430,12 +432,13 @@ static void ceph_netfs_issue_read(struct netfs_io_subrequest *subreq)
ceph_osdc_put_request(req);
if (err)
netfs_subreq_terminated(subreq, err, false);
- dout("%s: result %d\n", __func__, err);
+ doutc(cl, "%llx.%llx result %d\n", ceph_vinop(inode), err);
}
static int ceph_init_request(struct netfs_io_request *rreq, struct file *file)
{
struct inode *inode = rreq->inode;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
int got = 0, want = CEPH_CAP_FILE_CACHE;
struct ceph_netfs_request_data *priv;
int ret = 0;
@@ -467,12 +470,12 @@ static int ceph_init_request(struct netfs_io_request *rreq, struct file *file)
*/
ret = ceph_try_get_caps(inode, CEPH_CAP_FILE_RD, want, true, &got);
if (ret < 0) {
- dout("start_read %p, error getting cap\n", inode);
+ doutc(cl, "%llx.%llx, error getting cap\n", ceph_vinop(inode));
goto out;
}
if (!(got & want)) {
- dout("start_read %p, no cache cap\n", inode);
+ doutc(cl, "%llx.%llx, no cache cap\n", ceph_vinop(inode));
ret = -EACCES;
goto out;
}
@@ -567,13 +570,14 @@ get_oldest_context(struct inode *inode, struct ceph_writeback_ctl *ctl,
struct ceph_snap_context *page_snapc)
{
struct ceph_inode_info *ci = ceph_inode(inode);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_snap_context *snapc = NULL;
struct ceph_cap_snap *capsnap = NULL;
spin_lock(&ci->i_ceph_lock);
list_for_each_entry(capsnap, &ci->i_cap_snaps, ci_item) {
- dout(" cap_snap %p snapc %p has %d dirty pages\n", capsnap,
- capsnap->context, capsnap->dirty_pages);
+ doutc(cl, " capsnap %p snapc %p has %d dirty pages\n",
+ capsnap, capsnap->context, capsnap->dirty_pages);
if (!capsnap->dirty_pages)
continue;
@@ -605,8 +609,8 @@ get_oldest_context(struct inode *inode, struct ceph_writeback_ctl *ctl,
}
if (!snapc && ci->i_wrbuffer_ref_head) {
snapc = ceph_get_snap_context(ci->i_head_snapc);
- dout(" head snapc %p has %d dirty pages\n",
- snapc, ci->i_wrbuffer_ref_head);
+ doutc(cl, " head snapc %p has %d dirty pages\n", snapc,
+ ci->i_wrbuffer_ref_head);
if (ctl) {
ctl->i_size = i_size_read(inode);
ctl->truncate_size = ci->i_truncate_size;
@@ -663,6 +667,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
struct inode *inode = page->mapping->host;
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
+ struct ceph_client *cl = fsc->client;
struct ceph_snap_context *snapc, *oldest;
loff_t page_off = page_offset(page);
int err;
@@ -674,7 +679,8 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
bool caching = ceph_is_cache_enabled(inode);
struct page *bounce_page = NULL;
- dout("writepage %p idx %lu\n", page, page->index);
+ doutc(cl, "%llx.%llx page %p idx %lu\n", ceph_vinop(inode), page,
+ page->index);
if (ceph_inode_is_shutdown(inode))
return -EIO;
@@ -682,13 +688,14 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
/* verify this is a writeable snap context */
snapc = page_snap_context(page);
if (!snapc) {
- dout("writepage %p page %p not dirty?\n", inode, page);
+ doutc(cl, "%llx.%llx page %p not dirty?\n", ceph_vinop(inode),
+ page);
return 0;
}
oldest = get_oldest_context(inode, &ceph_wbc, snapc);
if (snapc->seq > oldest->seq) {
- dout("writepage %p page %p snapc %p not writeable - noop\n",
- inode, page, snapc);
+ doutc(cl, "%llx.%llx page %p snapc %p not writeable - noop\n",
+ ceph_vinop(inode), page, snapc);
/* we should only noop if called by kswapd */
WARN_ON(!(current->flags & PF_MEMALLOC));
ceph_put_snap_context(oldest);
@@ -699,8 +706,8 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
/* is this a partial page at end of file? */
if (page_off >= ceph_wbc.i_size) {
- dout("folio at %lu beyond eof %llu\n", folio->index,
- ceph_wbc.i_size);
+ doutc(cl, "%llx.%llx folio at %lu beyond eof %llu\n",
+ ceph_vinop(inode), folio->index, ceph_wbc.i_size);
folio_invalidate(folio, 0, folio_size(folio));
return 0;
}
@@ -709,8 +716,9 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
len = ceph_wbc.i_size - page_off;
wlen = IS_ENCRYPTED(inode) ? round_up(len, CEPH_FSCRYPT_BLOCK_SIZE) : len;
- dout("writepage %p page %p index %lu on %llu~%llu snapc %p seq %lld\n",
- inode, page, page->index, page_off, wlen, snapc, snapc->seq);
+ doutc(cl, "%llx.%llx page %p index %lu on %llu~%llu snapc %p seq %lld\n",
+ ceph_vinop(inode), page, page->index, page_off, wlen, snapc,
+ snapc->seq);
if (atomic_long_inc_return(&fsc->writeback_count) >
CONGESTION_ON_THRESH(fsc->mount_options->congestion_kb))
@@ -751,8 +759,9 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
osd_req_op_extent_osd_data_pages(req, 0,
bounce_page ? &bounce_page : &page, wlen, 0,
false, false);
- dout("writepage %llu~%llu (%llu bytes, %sencrypted)\n",
- page_off, len, wlen, IS_ENCRYPTED(inode) ? "" : "not ");
+ doutc(cl, "%llx.%llx %llu~%llu (%llu bytes, %sencrypted)\n",
+ ceph_vinop(inode), page_off, len, wlen,
+ IS_ENCRYPTED(inode) ? "" : "not ");
req->r_mtime = inode->i_mtime;
ceph_osdc_start_request(osdc, req);
@@ -771,19 +780,21 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
wbc = &tmp_wbc;
if (err == -ERESTARTSYS) {
/* killed by SIGKILL */
- dout("writepage interrupted page %p\n", page);
+ doutc(cl, "%llx.%llx interrupted page %p\n",
+ ceph_vinop(inode), page);
redirty_page_for_writepage(wbc, page);
end_page_writeback(page);
return err;
}
if (err == -EBLOCKLISTED)
fsc->blocklisted = true;
- dout("writepage setting page/mapping error %d %p\n",
- err, page);
+ doutc(cl, "%llx.%llx setting page/mapping error %d %p\n",
+ ceph_vinop(inode), err, page);
mapping_set_error(&inode->i_data, err);
wbc->pages_skipped++;
} else {
- dout("writepage cleaned page %p\n", page);
+ doutc(cl, "%llx.%llx cleaned page %p\n",
+ ceph_vinop(inode), page);
err = 0; /* vfs expects us to return 0 */
}
oldest = detach_page_private(page);
@@ -835,6 +846,7 @@ static void writepages_finish(struct ceph_osd_request *req)
{
struct inode *inode = req->r_inode;
struct ceph_inode_info *ci = ceph_inode(inode);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_osd_data *osd_data;
struct page *page;
int num_pages, total_pages = 0;
@@ -846,7 +858,7 @@ static void writepages_finish(struct ceph_osd_request *req)
unsigned int len = 0;
bool remove_page;
- dout("writepages_finish %p rc %d\n", inode, rc);
+ doutc(cl, "%llx.%llx rc %d\n", ceph_vinop(inode), rc);
if (rc < 0) {
mapping_set_error(mapping, rc);
ceph_set_error_write(ci);
@@ -868,8 +880,10 @@ static void writepages_finish(struct ceph_osd_request *req)
/* clean all pages */
for (i = 0; i < req->r_num_ops; i++) {
if (req->r_ops[i].op != CEPH_OSD_OP_WRITE) {
- pr_warn("%s incorrect op %d req %p index %d tid %llu\n",
- __func__, req->r_ops[i].op, req, i, req->r_tid);
+ pr_warn_client(cl,
+ "%llx.%llx incorrect op %d req %p index %d tid %llu\n",
+ ceph_vinop(inode), req->r_ops[i].op, req, i,
+ req->r_tid);
break;
}
@@ -896,7 +910,7 @@ static void writepages_finish(struct ceph_osd_request *req)
ceph_put_snap_context(detach_page_private(page));
end_page_writeback(page);
- dout("unlocking %p\n", page);
+ doutc(cl, "unlocking %p\n", page);
if (remove_page)
generic_error_remove_page(inode->i_mapping,
@@ -904,8 +918,9 @@ static void writepages_finish(struct ceph_osd_request *req)
unlock_page(page);
}
- dout("writepages_finish %p wrote %llu bytes cleaned %d pages\n",
- inode, osd_data->length, rc >= 0 ? num_pages : 0);
+ doutc(cl, "%llx.%llx wrote %llu bytes cleaned %d pages\n",
+ ceph_vinop(inode), osd_data->length,
+ rc >= 0 ? num_pages : 0);
release_pages(osd_data->pages, num_pages);
}
@@ -933,6 +948,7 @@ static int ceph_writepages_start(struct address_space *mapping,
struct inode *inode = mapping->host;
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
+ struct ceph_client *cl = fsc->client;
struct ceph_vino vino = ceph_vino(inode);
pgoff_t index, start_index, end = -1;
struct ceph_snap_context *snapc = NULL, *last_snapc = NULL, *pgsnapc;
@@ -950,15 +966,15 @@ static int ceph_writepages_start(struct address_space *mapping,
fsc->write_congested)
return 0;
- dout("writepages_start %p (mode=%s)\n", inode,
- wbc->sync_mode == WB_SYNC_NONE ? "NONE" :
- (wbc->sync_mode == WB_SYNC_ALL ? "ALL" : "HOLD"));
+ doutc(cl, "%llx.%llx (mode=%s)\n", ceph_vinop(inode),
+ wbc->sync_mode == WB_SYNC_NONE ? "NONE" :
+ (wbc->sync_mode == WB_SYNC_ALL ? "ALL" : "HOLD"));
if (ceph_inode_is_shutdown(inode)) {
if (ci->i_wrbuffer_ref > 0) {
- pr_warn_ratelimited(
- "writepage_start %p %lld forced umount\n",
- inode, ceph_ino(inode));
+ pr_warn_ratelimited_client(cl,
+ "%llx.%llx %lld forced umount\n",
+ ceph_vinop(inode), ceph_ino(inode));
}
mapping_set_error(mapping, -EIO);
return -EIO; /* we're in a forced umount, don't write! */
@@ -982,11 +998,11 @@ static int ceph_writepages_start(struct address_space *mapping,
if (!snapc) {
/* hmm, why does writepages get called when there
is no dirty data? */
- dout(" no snap context with dirty data?\n");
+ doutc(cl, " no snap context with dirty data?\n");
goto out;
}
- dout(" oldest snapc is %p seq %lld (%d snaps)\n",
- snapc, snapc->seq, snapc->num_snaps);
+ doutc(cl, " oldest snapc is %p seq %lld (%d snaps)\n", snapc,
+ snapc->seq, snapc->num_snaps);
should_loop = false;
if (ceph_wbc.head_snapc && snapc != last_snapc) {
@@ -996,13 +1012,13 @@ static int ceph_writepages_start(struct address_space *mapping,
end = -1;
if (index > 0)
should_loop = true;
- dout(" cyclic, start at %lu\n", index);
+ doutc(cl, " cyclic, start at %lu\n", index);
} else {
index = wbc->range_start >> PAGE_SHIFT;
end = wbc->range_end >> PAGE_SHIFT;
if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
range_whole = true;
- dout(" not cyclic, %lu to %lu\n", index, end);
+ doutc(cl, " not cyclic, %lu to %lu\n", index, end);
}
} else if (!ceph_wbc.head_snapc) {
/* Do not respect wbc->range_{start,end}. Dirty pages
@@ -1011,7 +1027,7 @@ static int ceph_writepages_start(struct address_space *mapping,
* associated with 'snapc' get written */
if (index > 0)
should_loop = true;
- dout(" non-head snapc, range whole\n");
+ doutc(cl, " non-head snapc, range whole\n");
}
if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
@@ -1034,12 +1050,12 @@ static int ceph_writepages_start(struct address_space *mapping,
get_more_pages:
nr_folios = filemap_get_folios_tag(mapping, &index,
end, tag, &fbatch);
- dout("pagevec_lookup_range_tag got %d\n", nr_folios);
+ doutc(cl, "pagevec_lookup_range_tag got %d\n", nr_folios);
if (!nr_folios && !locked_pages)
break;
for (i = 0; i < nr_folios && locked_pages < max_pages; i++) {
page = &fbatch.folios[i]->page;
- dout("? %p idx %lu\n", page, page->index);
+ doutc(cl, "? %p idx %lu\n", page, page->index);
if (locked_pages == 0)
lock_page(page); /* first page */
else if (!trylock_page(page))
@@ -1048,15 +1064,15 @@ static int ceph_writepages_start(struct address_space *mapping,
/* only dirty pages, or our accounting breaks */
if (unlikely(!PageDirty(page)) ||
unlikely(page->mapping != mapping)) {
- dout("!dirty or !mapping %p\n", page);
+ doutc(cl, "!dirty or !mapping %p\n", page);
unlock_page(page);
continue;
}
/* only if matching snap context */
pgsnapc = page_snap_context(page);
if (pgsnapc != snapc) {
- dout("page snapc %p %lld != oldest %p %lld\n",
- pgsnapc, pgsnapc->seq, snapc, snapc->seq);
+ doutc(cl, "page snapc %p %lld != oldest %p %lld\n",
+ pgsnapc, pgsnapc->seq, snapc, snapc->seq);
if (!should_loop &&
!ceph_wbc.head_snapc &&
wbc->sync_mode != WB_SYNC_NONE)
@@ -1067,8 +1083,8 @@ static int ceph_writepages_start(struct address_space *mapping,
if (page_offset(page) >= ceph_wbc.i_size) {
struct folio *folio = page_folio(page);
- dout("folio at %lu beyond eof %llu\n",
- folio->index, ceph_wbc.i_size);
+ doutc(cl, "folio at %lu beyond eof %llu\n",
+ folio->index, ceph_wbc.i_size);
if ((ceph_wbc.size_stable ||
folio_pos(folio) >= i_size_read(inode)) &&
folio_clear_dirty_for_io(folio))
@@ -1078,23 +1094,23 @@ static int ceph_writepages_start(struct address_space *mapping,
continue;
}
if (strip_unit_end && (page->index > strip_unit_end)) {
- dout("end of strip unit %p\n", page);
+ doutc(cl, "end of strip unit %p\n", page);
unlock_page(page);
break;
}
if (PageWriteback(page) || PageFsCache(page)) {
if (wbc->sync_mode == WB_SYNC_NONE) {
- dout("%p under writeback\n", page);
+ doutc(cl, "%p under writeback\n", page);
unlock_page(page);
continue;
}
- dout("waiting on writeback %p\n", page);
+ doutc(cl, "waiting on writeback %p\n", page);
wait_on_page_writeback(page);
wait_on_page_fscache(page);
}
if (!clear_page_dirty_for_io(page)) {
- dout("%p !clear_page_dirty_for_io\n", page);
+ doutc(cl, "%p !clear_page_dirty_for_io\n", page);
unlock_page(page);
continue;
}
@@ -1149,8 +1165,8 @@ static int ceph_writepages_start(struct address_space *mapping,
}
/* note position of first page in fbatch */
- dout("%p will write page %p idx %lu\n",
- inode, page, page->index);
+ doutc(cl, "%llx.%llx will write page %p idx %lu\n",
+ ceph_vinop(inode), page, page->index);
if (atomic_long_inc_return(&fsc->writeback_count) >
CONGESTION_ON_THRESH(
@@ -1164,8 +1180,9 @@ static int ceph_writepages_start(struct address_space *mapping,
locked_pages ? GFP_NOWAIT : GFP_NOFS);
if (IS_ERR(pages[locked_pages])) {
if (PTR_ERR(pages[locked_pages]) == -EINVAL)
- pr_err("%s: inode->i_blkbits=%hhu\n",
- __func__, inode->i_blkbits);
+ pr_err_client(cl,
+ "inode->i_blkbits=%hhu\n",
+ inode->i_blkbits);
/* better not fail on first page! */
BUG_ON(locked_pages == 0);
pages[locked_pages] = NULL;
@@ -1199,7 +1216,7 @@ static int ceph_writepages_start(struct address_space *mapping,
if (nr_folios && i == nr_folios &&
locked_pages < max_pages) {
- dout("reached end fbatch, trying for more\n");
+ doutc(cl, "reached end fbatch, trying for more\n");
folio_batch_release(&fbatch);
goto get_more_pages;
}
@@ -1260,8 +1277,8 @@ static int ceph_writepages_start(struct address_space *mapping,
/* Start a new extent */
osd_req_op_extent_dup_last(req, op_idx,
cur_offset - offset);
- dout("writepages got pages at %llu~%llu\n",
- offset, len);
+ doutc(cl, "got pages at %llu~%llu\n", offset,
+ len);
osd_req_op_extent_osd_data_pages(req, op_idx,
data_pages, len, 0,
from_pool, false);
@@ -1294,12 +1311,13 @@ static int ceph_writepages_start(struct address_space *mapping,
if (IS_ENCRYPTED(inode))
len = round_up(len, CEPH_FSCRYPT_BLOCK_SIZE);
- dout("writepages got pages at %llu~%llu\n", offset, len);
+ doutc(cl, "got pages at %llu~%llu\n", offset, len);
if (IS_ENCRYPTED(inode) &&
((offset | len) & ~CEPH_FSCRYPT_BLOCK_MASK))
- pr_warn("%s: bad encrypted write offset=%lld len=%llu\n",
- __func__, offset, len);
+ pr_warn_client(cl,
+ "bad encrypted write offset=%lld len=%llu\n",
+ offset, len);
osd_req_op_extent_osd_data_pages(req, op_idx, data_pages, len,
0, from_pool, false);
@@ -1351,14 +1369,14 @@ static int ceph_writepages_start(struct address_space *mapping,
done = true;
release_folios:
- dout("folio_batch release on %d folios (%p)\n", (int)fbatch.nr,
- fbatch.nr ? fbatch.folios[0] : NULL);
+ doutc(cl, "folio_batch release on %d folios (%p)\n",
+ (int)fbatch.nr, fbatch.nr ? fbatch.folios[0] : NULL);
folio_batch_release(&fbatch);
}
if (should_loop && !done) {
/* more to do; loop back to beginning of file */
- dout("writepages looping back to beginning of file\n");
+ doutc(cl, "looping back to beginning of file\n");
end = start_index - 1; /* OK even when start_index == 0 */
/* to write dirty pages associated with next snapc,
@@ -1396,7 +1414,8 @@ static int ceph_writepages_start(struct address_space *mapping,
out:
ceph_osdc_put_request(req);
ceph_put_snap_context(last_snapc);
- dout("writepages dend - startone, rc = %d\n", rc);
+ doutc(cl, "%llx.%llx dend - startone, rc = %d\n", ceph_vinop(inode),
+ rc);
return rc;
}
@@ -1430,11 +1449,12 @@ static struct ceph_snap_context *
ceph_find_incompatible(struct page *page)
{
struct inode *inode = page->mapping->host;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
if (ceph_inode_is_shutdown(inode)) {
- dout(" page %p %llx:%llx is shutdown\n", page,
- ceph_vinop(inode));
+ doutc(cl, " %llx.%llx page %p is shutdown\n",
+ ceph_vinop(inode), page);
return ERR_PTR(-ESTALE);
}
@@ -1455,13 +1475,15 @@ ceph_find_incompatible(struct page *page)
if (snapc->seq > oldest->seq) {
/* not writeable -- return it for the caller to deal with */
ceph_put_snap_context(oldest);
- dout(" page %p snapc %p not current or oldest\n", page, snapc);
+ doutc(cl, " %llx.%llx page %p snapc %p not current or oldest\n",
+ ceph_vinop(inode), page, snapc);
return ceph_get_snap_context(snapc);
}
ceph_put_snap_context(oldest);
/* yay, writeable, do it now (without dropping page lock) */
- dout(" page %p snapc %p not current, but oldest\n", page, snapc);
+ doutc(cl, " %llx.%llx page %p snapc %p not current, but oldest\n",
+ ceph_vinop(inode), page, snapc);
if (clear_page_dirty_for_io(page)) {
int r = writepage_nounlock(page, NULL);
if (r < 0)
@@ -1530,10 +1552,11 @@ static int ceph_write_end(struct file *file, struct address_space *mapping,
{
struct folio *folio = page_folio(subpage);
struct inode *inode = file_inode(file);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
bool check_cap = false;
- dout("write_end file %p inode %p folio %p %d~%d (%d)\n", file,
- inode, folio, (int)pos, (int)copied, (int)len);
+ doutc(cl, "%llx.%llx file %p folio %p %d~%d (%d)\n", ceph_vinop(inode),
+ file, folio, (int)pos, (int)copied, (int)len);
if (!folio_test_uptodate(folio)) {
/* just return that nothing was copied on a short copy */
@@ -1593,6 +1616,7 @@ static vm_fault_t ceph_filemap_fault(struct vm_fault *vmf)
struct vm_area_struct *vma = vmf->vma;
struct inode *inode = file_inode(vma->vm_file);
struct ceph_inode_info *ci = ceph_inode(inode);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_file_info *fi = vma->vm_file->private_data;
loff_t off = (loff_t)vmf->pgoff << PAGE_SHIFT;
int want, got, err;
@@ -1604,8 +1628,8 @@ static vm_fault_t ceph_filemap_fault(struct vm_fault *vmf)
ceph_block_sigs(&oldset);
- dout("filemap_fault %p %llx.%llx %llu trying to get caps\n",
- inode, ceph_vinop(inode), off);
+ doutc(cl, "%llx.%llx %llu trying to get caps\n",
+ ceph_vinop(inode), off);
if (fi->fmode & CEPH_FILE_MODE_LAZY)
want = CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO;
else
@@ -1616,8 +1640,8 @@ static vm_fault_t ceph_filemap_fault(struct vm_fault *vmf)
if (err < 0)
goto out_restore;
- dout("filemap_fault %p %llu got cap refs on %s\n",
- inode, off, ceph_cap_string(got));
+ doutc(cl, "%llx.%llx %llu got cap refs on %s\n", ceph_vinop(inode),
+ off, ceph_cap_string(got));
if ((got & (CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO)) ||
!ceph_has_inline_data(ci)) {
@@ -1625,8 +1649,8 @@ static vm_fault_t ceph_filemap_fault(struct vm_fault *vmf)
ceph_add_rw_context(fi, &rw_ctx);
ret = filemap_fault(vmf);
ceph_del_rw_context(fi, &rw_ctx);
- dout("filemap_fault %p %llu drop cap refs %s ret %x\n",
- inode, off, ceph_cap_string(got), ret);
+ doutc(cl, "%llx.%llx %llu drop cap refs %s ret %x\n",
+ ceph_vinop(inode), off, ceph_cap_string(got), ret);
} else
err = -EAGAIN;
@@ -1667,8 +1691,8 @@ static vm_fault_t ceph_filemap_fault(struct vm_fault *vmf)
ret = VM_FAULT_MAJOR | VM_FAULT_LOCKED;
out_inline:
filemap_invalidate_unlock_shared(mapping);
- dout("filemap_fault %p %llu read inline data ret %x\n",
- inode, off, ret);
+ doutc(cl, "%llx.%llx %llu read inline data ret %x\n",
+ ceph_vinop(inode), off, ret);
}
out_restore:
ceph_restore_sigs(&oldset);
@@ -1682,6 +1706,7 @@ static vm_fault_t ceph_page_mkwrite(struct vm_fault *vmf)
{
struct vm_area_struct *vma = vmf->vma;
struct inode *inode = file_inode(vma->vm_file);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_file_info *fi = vma->vm_file->private_data;
struct ceph_cap_flush *prealloc_cf;
@@ -1708,8 +1733,8 @@ static vm_fault_t ceph_page_mkwrite(struct vm_fault *vmf)
else
len = offset_in_thp(page, size);
- dout("page_mkwrite %p %llx.%llx %llu~%zd getting caps i_size %llu\n",
- inode, ceph_vinop(inode), off, len, size);
+ doutc(cl, "%llx.%llx %llu~%zd getting caps i_size %llu\n",
+ ceph_vinop(inode), off, len, size);
if (fi->fmode & CEPH_FILE_MODE_LAZY)
want = CEPH_CAP_FILE_BUFFER | CEPH_CAP_FILE_LAZYIO;
else
@@ -1720,8 +1745,8 @@ static vm_fault_t ceph_page_mkwrite(struct vm_fault *vmf)
if (err < 0)
goto out_free;
- dout("page_mkwrite %p %llu~%zd got cap refs on %s\n",
- inode, off, len, ceph_cap_string(got));
+ doutc(cl, "%llx.%llx %llu~%zd got cap refs on %s\n", ceph_vinop(inode),
+ off, len, ceph_cap_string(got));
/* Update time before taking page lock */
file_update_time(vma->vm_file);
@@ -1769,8 +1794,8 @@ static vm_fault_t ceph_page_mkwrite(struct vm_fault *vmf)
__mark_inode_dirty(inode, dirty);
}
- dout("page_mkwrite %p %llu~%zd dropping cap refs on %s ret %x\n",
- inode, off, len, ceph_cap_string(got), ret);
+ doutc(cl, "%llx.%llx %llu~%zd dropping cap refs on %s ret %x\n",
+ ceph_vinop(inode), off, len, ceph_cap_string(got), ret);
ceph_put_cap_refs_async(ci, got);
out_free:
ceph_restore_sigs(&oldset);
@@ -1784,6 +1809,7 @@ static vm_fault_t ceph_page_mkwrite(struct vm_fault *vmf)
void ceph_fill_inline_data(struct inode *inode, struct page *locked_page,
char *data, size_t len)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct address_space *mapping = inode->i_mapping;
struct page *page;
@@ -1804,8 +1830,8 @@ void ceph_fill_inline_data(struct inode *inode, struct page *locked_page,
}
}
- dout("fill_inline_data %p %llx.%llx len %zu locked_page %p\n",
- inode, ceph_vinop(inode), len, locked_page);
+ doutc(cl, "%p %llx.%llx len %zu locked_page %p\n", inode,
+ ceph_vinop(inode), len, locked_page);
if (len > 0) {
void *kaddr = kmap_atomic(page);
@@ -1830,6 +1856,7 @@ int ceph_uninline_data(struct file *file)
struct inode *inode = file_inode(file);
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
+ struct ceph_client *cl = fsc->client;
struct ceph_osd_request *req = NULL;
struct ceph_cap_flush *prealloc_cf = NULL;
struct folio *folio = NULL;
@@ -1843,8 +1870,8 @@ int ceph_uninline_data(struct file *file)
inline_version = ci->i_inline_version;
spin_unlock(&ci->i_ceph_lock);
- dout("uninline_data %p %llx.%llx inline_version %llu\n",
- inode, ceph_vinop(inode), inline_version);
+ doutc(cl, "%llx.%llx inline_version %llu\n", ceph_vinop(inode),
+ inline_version);
if (ceph_inode_is_shutdown(inode)) {
err = -EIO;
@@ -1975,8 +2002,8 @@ int ceph_uninline_data(struct file *file)
out:
ceph_put_snap_context(snapc);
ceph_free_cap_flush(prealloc_cf);
- dout("uninline_data %p %llx.%llx inline_version %llu = %d\n",
- inode, ceph_vinop(inode), inline_version, err);
+ doutc(cl, "%llx.%llx inline_version %llu = %d\n",
+ ceph_vinop(inode), inline_version, err);
return err;
}
@@ -2005,6 +2032,7 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci,
{
struct ceph_fs_client *fsc = ceph_inode_to_fs_client(&ci->netfs.inode);
struct ceph_mds_client *mdsc = fsc->mdsc;
+ struct ceph_client *cl = fsc->client;
struct ceph_osd_request *rd_req = NULL, *wr_req = NULL;
struct rb_node **p, *parent;
struct ceph_pool_perm *perm;
@@ -2039,10 +2067,10 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci,
goto out;
if (pool_ns)
- dout("__ceph_pool_perm_get pool %lld ns %.*s no perm cached\n",
- pool, (int)pool_ns->len, pool_ns->str);
+ doutc(cl, "pool %lld ns %.*s no perm cached\n", pool,
+ (int)pool_ns->len, pool_ns->str);
else
- dout("__ceph_pool_perm_get pool %lld no perm cached\n", pool);
+ doutc(cl, "pool %lld no perm cached\n", pool);
down_write(&mdsc->pool_perm_rwsem);
p = &mdsc->pool_perm_tree.rb_node;
@@ -2167,15 +2195,16 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci,
if (!err)
err = have;
if (pool_ns)
- dout("__ceph_pool_perm_get pool %lld ns %.*s result = %d\n",
- pool, (int)pool_ns->len, pool_ns->str, err);
+ doutc(cl, "pool %lld ns %.*s result = %d\n", pool,
+ (int)pool_ns->len, pool_ns->str, err);
else
- dout("__ceph_pool_perm_get pool %lld result = %d\n", pool, err);
+ doutc(cl, "pool %lld result = %d\n", pool, err);
return err;
}
int ceph_pool_perm_check(struct inode *inode, int need)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_string *pool_ns;
s64 pool;
@@ -2205,13 +2234,11 @@ int ceph_pool_perm_check(struct inode *inode, int need)
check:
if (flags & CEPH_I_POOL_PERM) {
if ((need & CEPH_CAP_FILE_RD) && !(flags & CEPH_I_POOL_RD)) {
- dout("ceph_pool_perm_check pool %lld no read perm\n",
- pool);
+ doutc(cl, "pool %lld no read perm\n", pool);
return -EPERM;
}
if ((need & CEPH_CAP_FILE_WR) && !(flags & CEPH_I_POOL_WR)) {
- dout("ceph_pool_perm_check pool %lld no write perm\n",
- pool);
+ doutc(cl, "pool %lld no write perm\n", pool);
return -EPERM;
}
return 0;
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 67e6cb0eba3a..941799cb5331 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -186,10 +186,10 @@ static void __ceph_unreserve_caps(struct ceph_mds_client *mdsc, int nr_caps)
mdsc->caps_avail_count += nr_caps;
}
- dout("%s: caps %d = %d used + %d resv + %d avail\n",
- __func__,
- mdsc->caps_total_count, mdsc->caps_use_count,
- mdsc->caps_reserve_count, mdsc->caps_avail_count);
+ doutc(mdsc->fsc->client,
+ "caps %d = %d used + %d resv + %d avail\n",
+ mdsc->caps_total_count, mdsc->caps_use_count,
+ mdsc->caps_reserve_count, mdsc->caps_avail_count);
BUG_ON(mdsc->caps_total_count != mdsc->caps_use_count +
mdsc->caps_reserve_count +
mdsc->caps_avail_count);
@@ -202,6 +202,7 @@ static void __ceph_unreserve_caps(struct ceph_mds_client *mdsc, int nr_caps)
int ceph_reserve_caps(struct ceph_mds_client *mdsc,
struct ceph_cap_reservation *ctx, int need)
{
+ struct ceph_client *cl = mdsc->fsc->client;
int i, j;
struct ceph_cap *cap;
int have;
@@ -212,7 +213,7 @@ int ceph_reserve_caps(struct ceph_mds_client *mdsc,
struct ceph_mds_session *s;
LIST_HEAD(newcaps);
- dout("reserve caps ctx=%p need=%d\n", ctx, need);
+ doutc(cl, "ctx=%p need=%d\n", ctx, need);
/* first reserve any caps that are already allocated */
spin_lock(&mdsc->caps_list_lock);
@@ -272,8 +273,8 @@ int ceph_reserve_caps(struct ceph_mds_client *mdsc,
continue;
}
- pr_warn("reserve caps ctx=%p ENOMEM need=%d got=%d\n",
- ctx, need, have + alloc);
+ pr_warn_client(cl, "ctx=%p ENOMEM need=%d got=%d\n", ctx, need,
+ have + alloc);
err = -ENOMEM;
break;
}
@@ -298,20 +299,21 @@ int ceph_reserve_caps(struct ceph_mds_client *mdsc,
spin_unlock(&mdsc->caps_list_lock);
- dout("reserve caps ctx=%p %d = %d used + %d resv + %d avail\n",
- ctx, mdsc->caps_total_count, mdsc->caps_use_count,
- mdsc->caps_reserve_count, mdsc->caps_avail_count);
+ doutc(cl, "ctx=%p %d = %d used + %d resv + %d avail\n", ctx,
+ mdsc->caps_total_count, mdsc->caps_use_count,
+ mdsc->caps_reserve_count, mdsc->caps_avail_count);
return err;
}
void ceph_unreserve_caps(struct ceph_mds_client *mdsc,
struct ceph_cap_reservation *ctx)
{
+ struct ceph_client *cl = mdsc->fsc->client;
bool reclaim = false;
if (!ctx->count)
return;
- dout("unreserve caps ctx=%p count=%d\n", ctx, ctx->count);
+ doutc(cl, "ctx=%p count=%d\n", ctx, ctx->count);
spin_lock(&mdsc->caps_list_lock);
__ceph_unreserve_caps(mdsc, ctx->count);
ctx->count = 0;
@@ -328,6 +330,7 @@ void ceph_unreserve_caps(struct ceph_mds_client *mdsc,
struct ceph_cap *ceph_get_cap(struct ceph_mds_client *mdsc,
struct ceph_cap_reservation *ctx)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_cap *cap = NULL;
/* temporary, until we do something about cap import/export */
@@ -359,9 +362,9 @@ struct ceph_cap *ceph_get_cap(struct ceph_mds_client *mdsc,
}
spin_lock(&mdsc->caps_list_lock);
- dout("get_cap ctx=%p (%d) %d = %d used + %d resv + %d avail\n",
- ctx, ctx->count, mdsc->caps_total_count, mdsc->caps_use_count,
- mdsc->caps_reserve_count, mdsc->caps_avail_count);
+ doutc(cl, "ctx=%p (%d) %d = %d used + %d resv + %d avail\n", ctx,
+ ctx->count, mdsc->caps_total_count, mdsc->caps_use_count,
+ mdsc->caps_reserve_count, mdsc->caps_avail_count);
BUG_ON(!ctx->count);
BUG_ON(ctx->count > mdsc->caps_reserve_count);
BUG_ON(list_empty(&mdsc->caps_list));
@@ -382,10 +385,12 @@ struct ceph_cap *ceph_get_cap(struct ceph_mds_client *mdsc,
void ceph_put_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap)
{
+ struct ceph_client *cl = mdsc->fsc->client;
+
spin_lock(&mdsc->caps_list_lock);
- dout("put_cap %p %d = %d used + %d resv + %d avail\n",
- cap, mdsc->caps_total_count, mdsc->caps_use_count,
- mdsc->caps_reserve_count, mdsc->caps_avail_count);
+ doutc(cl, "%p %d = %d used + %d resv + %d avail\n", cap,
+ mdsc->caps_total_count, mdsc->caps_use_count,
+ mdsc->caps_reserve_count, mdsc->caps_avail_count);
mdsc->caps_use_count--;
/*
* Keep some preallocated caps around (ceph_min_count), to
@@ -491,11 +496,13 @@ static void __insert_cap_node(struct ceph_inode_info *ci,
static void __cap_set_timeouts(struct ceph_mds_client *mdsc,
struct ceph_inode_info *ci)
{
+ struct inode *inode = &ci->netfs.inode;
struct ceph_mount_options *opt = mdsc->fsc->mount_options;
+
ci->i_hold_caps_max = round_jiffies(jiffies +
opt->caps_wanted_delay_max * HZ);
- dout("__cap_set_timeouts %p %lu\n", &ci->netfs.inode,
- ci->i_hold_caps_max - jiffies);
+ doutc(mdsc->fsc->client, "%p %llx.%llx %lu\n", inode,
+ ceph_vinop(inode), ci->i_hold_caps_max - jiffies);
}
/*
@@ -509,8 +516,11 @@ static void __cap_set_timeouts(struct ceph_mds_client *mdsc,
static void __cap_delay_requeue(struct ceph_mds_client *mdsc,
struct ceph_inode_info *ci)
{
- dout("__cap_delay_requeue %p flags 0x%lx at %lu\n", &ci->netfs.inode,
- ci->i_ceph_flags, ci->i_hold_caps_max);
+ struct inode *inode = &ci->netfs.inode;
+
+ doutc(mdsc->fsc->client, "%p %llx.%llx flags 0x%lx at %lu\n",
+ inode, ceph_vinop(inode), ci->i_ceph_flags,
+ ci->i_hold_caps_max);
if (!mdsc->stopping) {
spin_lock(&mdsc->cap_delay_lock);
if (!list_empty(&ci->i_cap_delay_list)) {
@@ -533,7 +543,9 @@ static void __cap_delay_requeue(struct ceph_mds_client *mdsc,
static void __cap_delay_requeue_front(struct ceph_mds_client *mdsc,
struct ceph_inode_info *ci)
{
- dout("__cap_delay_requeue_front %p\n", &ci->netfs.inode);
+ struct inode *inode = &ci->netfs.inode;
+
+ doutc(mdsc->fsc->client, "%p %llx.%llx\n", inode, ceph_vinop(inode));
spin_lock(&mdsc->cap_delay_lock);
ci->i_ceph_flags |= CEPH_I_FLUSH;
if (!list_empty(&ci->i_cap_delay_list))
@@ -550,7 +562,9 @@ static void __cap_delay_requeue_front(struct ceph_mds_client *mdsc,
static void __cap_delay_cancel(struct ceph_mds_client *mdsc,
struct ceph_inode_info *ci)
{
- dout("__cap_delay_cancel %p\n", &ci->netfs.inode);
+ struct inode *inode = &ci->netfs.inode;
+
+ doutc(mdsc->fsc->client, "%p %llx.%llx\n", inode, ceph_vinop(inode));
if (list_empty(&ci->i_cap_delay_list))
return;
spin_lock(&mdsc->cap_delay_lock);
@@ -562,6 +576,9 @@ static void __cap_delay_cancel(struct ceph_mds_client *mdsc,
static void __check_cap_issue(struct ceph_inode_info *ci, struct ceph_cap *cap,
unsigned issued)
{
+ struct inode *inode = &ci->netfs.inode;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
+
unsigned had = __ceph_caps_issued(ci, NULL);
lockdep_assert_held(&ci->i_ceph_lock);
@@ -586,7 +603,7 @@ static void __check_cap_issue(struct ceph_inode_info *ci, struct ceph_cap *cap,
if (issued & CEPH_CAP_FILE_SHARED)
atomic_inc(&ci->i_shared_gen);
if (S_ISDIR(ci->netfs.inode.i_mode)) {
- dout(" marking %p NOT complete\n", &ci->netfs.inode);
+ doutc(cl, " marking %p NOT complete\n", inode);
__ceph_dir_clear_complete(ci);
}
}
@@ -636,6 +653,7 @@ void ceph_add_cap(struct inode *inode,
struct ceph_cap **new_cap)
{
struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_cap *cap;
int mds = session->s_mds;
@@ -644,8 +662,9 @@ void ceph_add_cap(struct inode *inode,
lockdep_assert_held(&ci->i_ceph_lock);
- dout("add_cap %p mds%d cap %llx %s seq %d\n", inode,
- session->s_mds, cap_id, ceph_cap_string(issued), seq);
+ doutc(cl, "%p %llx.%llx mds%d cap %llx %s seq %d\n", inode,
+ ceph_vinop(inode), session->s_mds, cap_id,
+ ceph_cap_string(issued), seq);
gen = atomic_read(&session->s_cap_gen);
@@ -723,9 +742,9 @@ void ceph_add_cap(struct inode *inode,
actual_wanted = __ceph_caps_wanted(ci);
if ((wanted & ~actual_wanted) ||
(issued & ~actual_wanted & CEPH_CAP_ANY_WR)) {
- dout(" issued %s, mds wanted %s, actual %s, queueing\n",
- ceph_cap_string(issued), ceph_cap_string(wanted),
- ceph_cap_string(actual_wanted));
+ doutc(cl, "issued %s, mds wanted %s, actual %s, queueing\n",
+ ceph_cap_string(issued), ceph_cap_string(wanted),
+ ceph_cap_string(actual_wanted));
__cap_delay_requeue(mdsc, ci);
}
@@ -742,9 +761,9 @@ void ceph_add_cap(struct inode *inode,
WARN_ON(ci->i_auth_cap == cap);
}
- dout("add_cap inode %p (%llx.%llx) cap %p %s now %s seq %d mds%d\n",
- inode, ceph_vinop(inode), cap, ceph_cap_string(issued),
- ceph_cap_string(issued|cap->issued), seq, mds);
+ doutc(cl, "inode %p %llx.%llx cap %p %s now %s seq %d mds%d\n",
+ inode, ceph_vinop(inode), cap, ceph_cap_string(issued),
+ ceph_cap_string(issued|cap->issued), seq, mds);
cap->cap_id = cap_id;
cap->issued = issued;
cap->implemented |= issued;
@@ -766,6 +785,8 @@ void ceph_add_cap(struct inode *inode,
*/
static int __cap_is_valid(struct ceph_cap *cap)
{
+ struct inode *inode = &cap->ci->netfs.inode;
+ struct ceph_client *cl = cap->session->s_mdsc->fsc->client;
unsigned long ttl;
u32 gen;
@@ -773,9 +794,9 @@ static int __cap_is_valid(struct ceph_cap *cap)
ttl = cap->session->s_cap_ttl;
if (cap->cap_gen < gen || time_after_eq(jiffies, ttl)) {
- dout("__cap_is_valid %p cap %p issued %s "
- "but STALE (gen %u vs %u)\n", &cap->ci->netfs.inode,
- cap, ceph_cap_string(cap->issued), cap->cap_gen, gen);
+ doutc(cl, "%p %llx.%llx cap %p issued %s but STALE (gen %u vs %u)\n",
+ inode, ceph_vinop(inode), cap,
+ ceph_cap_string(cap->issued), cap->cap_gen, gen);
return 0;
}
@@ -789,6 +810,8 @@ static int __cap_is_valid(struct ceph_cap *cap)
*/
int __ceph_caps_issued(struct ceph_inode_info *ci, int *implemented)
{
+ struct inode *inode = &ci->netfs.inode;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
int have = ci->i_snap_caps;
struct ceph_cap *cap;
struct rb_node *p;
@@ -799,8 +822,8 @@ int __ceph_caps_issued(struct ceph_inode_info *ci, int *implemented)
cap = rb_entry(p, struct ceph_cap, ci_node);
if (!__cap_is_valid(cap))
continue;
- dout("__ceph_caps_issued %p cap %p issued %s\n",
- &ci->netfs.inode, cap, ceph_cap_string(cap->issued));
+ doutc(cl, "%p %llx.%llx cap %p issued %s\n", inode,
+ ceph_vinop(inode), cap, ceph_cap_string(cap->issued));
have |= cap->issued;
if (implemented)
*implemented |= cap->implemented;
@@ -843,16 +866,18 @@ int __ceph_caps_issued_other(struct ceph_inode_info *ci, struct ceph_cap *ocap)
*/
static void __touch_cap(struct ceph_cap *cap)
{
+ struct inode *inode = &cap->ci->netfs.inode;
struct ceph_mds_session *s = cap->session;
+ struct ceph_client *cl = s->s_mdsc->fsc->client;
spin_lock(&s->s_cap_lock);
if (!s->s_cap_iterator) {
- dout("__touch_cap %p cap %p mds%d\n", &cap->ci->netfs.inode, cap,
- s->s_mds);
+ doutc(cl, "%p %llx.%llx cap %p mds%d\n", inode,
+ ceph_vinop(inode), cap, s->s_mds);
list_move_tail(&cap->session_caps, &s->s_caps);
} else {
- dout("__touch_cap %p cap %p mds%d NOP, iterating over caps\n",
- &cap->ci->netfs.inode, cap, s->s_mds);
+ doutc(cl, "%p %llx.%llx cap %p mds%d NOP, iterating over caps\n",
+ inode, ceph_vinop(inode), cap, s->s_mds);
}
spin_unlock(&s->s_cap_lock);
}
@@ -864,15 +889,16 @@ static void __touch_cap(struct ceph_cap *cap)
*/
int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch)
{
+ struct inode *inode = &ci->netfs.inode;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_cap *cap;
struct rb_node *p;
int have = ci->i_snap_caps;
if ((have & mask) == mask) {
- dout("__ceph_caps_issued_mask ino 0x%llx snap issued %s"
- " (mask %s)\n", ceph_ino(&ci->netfs.inode),
- ceph_cap_string(have),
- ceph_cap_string(mask));
+ doutc(cl, "mask %p %llx.%llx snap issued %s (mask %s)\n",
+ inode, ceph_vinop(inode), ceph_cap_string(have),
+ ceph_cap_string(mask));
return 1;
}
@@ -881,10 +907,10 @@ int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch)
if (!__cap_is_valid(cap))
continue;
if ((cap->issued & mask) == mask) {
- dout("__ceph_caps_issued_mask ino 0x%llx cap %p issued %s"
- " (mask %s)\n", ceph_ino(&ci->netfs.inode), cap,
- ceph_cap_string(cap->issued),
- ceph_cap_string(mask));
+ doutc(cl, "mask %p %llx.%llx cap %p issued %s (mask %s)\n",
+ inode, ceph_vinop(inode), cap,
+ ceph_cap_string(cap->issued),
+ ceph_cap_string(mask));
if (touch)
__touch_cap(cap);
return 1;
@@ -893,10 +919,10 @@ int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch)
/* does a combination of caps satisfy mask? */
have |= cap->issued;
if ((have & mask) == mask) {
- dout("__ceph_caps_issued_mask ino 0x%llx combo issued %s"
- " (mask %s)\n", ceph_ino(&ci->netfs.inode),
- ceph_cap_string(cap->issued),
- ceph_cap_string(mask));
+ doutc(cl, "mask %p %llx.%llx combo issued %s (mask %s)\n",
+ inode, ceph_vinop(inode),
+ ceph_cap_string(cap->issued),
+ ceph_cap_string(mask));
if (touch) {
struct rb_node *q;
@@ -954,13 +980,14 @@ int __ceph_caps_revoking_other(struct ceph_inode_info *ci,
int ceph_caps_revoking(struct ceph_inode_info *ci, int mask)
{
struct inode *inode = &ci->netfs.inode;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
int ret;
spin_lock(&ci->i_ceph_lock);
ret = __ceph_caps_revoking_other(ci, NULL, mask);
spin_unlock(&ci->i_ceph_lock);
- dout("ceph_caps_revoking %p %s = %d\n", inode,
- ceph_cap_string(mask), ret);
+ doutc(cl, "%p %llx.%llx %s = %d\n", inode, ceph_vinop(inode),
+ ceph_cap_string(mask), ret);
return ret;
}
@@ -1107,19 +1134,21 @@ int ceph_is_any_caps(struct inode *inode)
void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
{
struct ceph_mds_session *session = cap->session;
+ struct ceph_client *cl = session->s_mdsc->fsc->client;
struct ceph_inode_info *ci = cap->ci;
+ struct inode *inode = &ci->netfs.inode;
struct ceph_mds_client *mdsc;
int removed = 0;
/* 'ci' being NULL means the remove have already occurred */
if (!ci) {
- dout("%s: cap inode is NULL\n", __func__);
+ doutc(cl, "inode is NULL\n");
return;
}
lockdep_assert_held(&ci->i_ceph_lock);
- dout("__ceph_remove_cap %p from %p\n", cap, &ci->netfs.inode);
+ doutc(cl, "%p from %p %llx.%llx\n", cap, inode, ceph_vinop(inode));
mdsc = ceph_inode_to_fs_client(&ci->netfs.inode)->mdsc;
@@ -1132,8 +1161,8 @@ void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
spin_lock(&session->s_cap_lock);
if (session->s_cap_iterator == cap) {
/* not yet, we are iterating over this very cap */
- dout("__ceph_remove_cap delaying %p removal from session %p\n",
- cap, cap->session);
+ doutc(cl, "delaying %p removal from session %p\n", cap,
+ cap->session);
} else {
list_del_init(&cap->session_caps);
session->s_nr_caps--;
@@ -1186,7 +1215,7 @@ void ceph_remove_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
/* 'ci' being NULL means the remove have already occurred */
if (!ci) {
- dout("%s: cap inode is NULL\n", __func__);
+ doutc(mdsc->fsc->client, "inode is NULL\n");
return;
}
@@ -1228,15 +1257,19 @@ static void encode_cap_msg(struct ceph_msg *msg, struct cap_msg_args *arg)
{
struct ceph_mds_caps *fc;
void *p;
- struct ceph_osd_client *osdc = &arg->session->s_mdsc->fsc->client->osdc;
-
- dout("%s %s %llx %llx caps %s wanted %s dirty %s seq %u/%u tid %llu/%llu mseq %u follows %lld size %llu/%llu xattr_ver %llu xattr_len %d\n",
- __func__, ceph_cap_op_name(arg->op), arg->cid, arg->ino,
- ceph_cap_string(arg->caps), ceph_cap_string(arg->wanted),
- ceph_cap_string(arg->dirty), arg->seq, arg->issue_seq,
- arg->flush_tid, arg->oldest_flush_tid, arg->mseq, arg->follows,
- arg->size, arg->max_size, arg->xattr_version,
- arg->xattr_buf ? (int)arg->xattr_buf->vec.iov_len : 0);
+ struct ceph_mds_client *mdsc = arg->session->s_mdsc;
+ struct ceph_osd_client *osdc = &mdsc->fsc->client->osdc;
+
+ doutc(mdsc->fsc->client,
+ "%s %llx %llx caps %s wanted %s dirty %s seq %u/%u"
+ " tid %llu/%llu mseq %u follows %lld size %llu/%llu"
+ " xattr_ver %llu xattr_len %d\n",
+ ceph_cap_op_name(arg->op), arg->cid, arg->ino,
+ ceph_cap_string(arg->caps), ceph_cap_string(arg->wanted),
+ ceph_cap_string(arg->dirty), arg->seq, arg->issue_seq,
+ arg->flush_tid, arg->oldest_flush_tid, arg->mseq, arg->follows,
+ arg->size, arg->max_size, arg->xattr_version,
+ arg->xattr_buf ? (int)arg->xattr_buf->vec.iov_len : 0);
msg->hdr.version = cpu_to_le16(12);
msg->hdr.tid = cpu_to_le64(arg->flush_tid);
@@ -1373,6 +1406,7 @@ static void __prep_cap(struct cap_msg_args *arg, struct ceph_cap *cap,
{
struct ceph_inode_info *ci = cap->ci;
struct inode *inode = &ci->netfs.inode;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
int held, revoking;
lockdep_assert_held(&ci->i_ceph_lock);
@@ -1381,10 +1415,10 @@ static void __prep_cap(struct cap_msg_args *arg, struct ceph_cap *cap,
revoking = cap->implemented & ~cap->issued;
retain &= ~revoking;
- dout("%s %p cap %p session %p %s -> %s (revoking %s)\n",
- __func__, inode, cap, cap->session,
- ceph_cap_string(held), ceph_cap_string(held & retain),
- ceph_cap_string(revoking));
+ doutc(cl, "%p %llx.%llx cap %p session %p %s -> %s (revoking %s)\n",
+ inode, ceph_vinop(inode), cap, cap->session,
+ ceph_cap_string(held), ceph_cap_string(held & retain),
+ ceph_cap_string(revoking));
BUG_ON((retain & CEPH_CAP_PIN) == 0);
ci->i_ceph_flags &= ~CEPH_I_FLUSH;
@@ -1500,13 +1534,16 @@ static void __send_cap(struct cap_msg_args *arg, struct ceph_inode_info *ci)
{
struct ceph_msg *msg;
struct inode *inode = &ci->netfs.inode;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
msg = ceph_msg_new(CEPH_MSG_CLIENT_CAPS, cap_msg_size(arg), GFP_NOFS,
false);
if (!msg) {
- pr_err("error allocating cap msg: ino (%llx.%llx) flushing %s tid %llu, requeuing cap.\n",
- ceph_vinop(inode), ceph_cap_string(arg->dirty),
- arg->flush_tid);
+ pr_err_client(cl,
+ "error allocating cap msg: ino (%llx.%llx)"
+ " flushing %s tid %llu, requeuing cap.\n",
+ ceph_vinop(inode), ceph_cap_string(arg->dirty),
+ arg->flush_tid);
spin_lock(&ci->i_ceph_lock);
__cap_delay_requeue(arg->session->s_mdsc, ci);
spin_unlock(&ci->i_ceph_lock);
@@ -1596,11 +1633,13 @@ static void __ceph_flush_snaps(struct ceph_inode_info *ci,
{
struct inode *inode = &ci->netfs.inode;
struct ceph_mds_client *mdsc = session->s_mdsc;
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_cap_snap *capsnap;
u64 oldest_flush_tid = 0;
u64 first_tid = 1, last_tid = 0;
- dout("__flush_snaps %p session %p\n", inode, session);
+ doutc(cl, "%p %llx.%llx session %p\n", inode, ceph_vinop(inode),
+ session);
list_for_each_entry(capsnap, &ci->i_cap_snaps, ci_item) {
/*
@@ -1615,7 +1654,7 @@ static void __ceph_flush_snaps(struct ceph_inode_info *ci,
/* only flush each capsnap once */
if (capsnap->cap_flush.tid > 0) {
- dout(" already flushed %p, skipping\n", capsnap);
+ doutc(cl, "already flushed %p, skipping\n", capsnap);
continue;
}
@@ -1647,8 +1686,8 @@ static void __ceph_flush_snaps(struct ceph_inode_info *ci,
int ret;
if (!(cap && cap->session == session)) {
- dout("__flush_snaps %p auth cap %p not mds%d, "
- "stop\n", inode, cap, session->s_mds);
+ doutc(cl, "%p %llx.%llx auth cap %p not mds%d, stop\n",
+ inode, ceph_vinop(inode), cap, session->s_mds);
break;
}
@@ -1669,15 +1708,17 @@ static void __ceph_flush_snaps(struct ceph_inode_info *ci,
refcount_inc(&capsnap->nref);
spin_unlock(&ci->i_ceph_lock);
- dout("__flush_snaps %p capsnap %p tid %llu %s\n",
- inode, capsnap, cf->tid, ceph_cap_string(capsnap->dirty));
+ doutc(cl, "%p %llx.%llx capsnap %p tid %llu %s\n", inode,
+ ceph_vinop(inode), capsnap, cf->tid,
+ ceph_cap_string(capsnap->dirty));
ret = __send_flush_snap(inode, session, capsnap, cap->mseq,
oldest_flush_tid);
if (ret < 0) {
- pr_err("__flush_snaps: error sending cap flushsnap, "
- "ino (%llx.%llx) tid %llu follows %llu\n",
- ceph_vinop(inode), cf->tid, capsnap->follows);
+ pr_err_client(cl, "error sending cap flushsnap, "
+ "ino (%llx.%llx) tid %llu follows %llu\n",
+ ceph_vinop(inode), cf->tid,
+ capsnap->follows);
}
ceph_put_cap_snap(capsnap);
@@ -1690,27 +1731,28 @@ void ceph_flush_snaps(struct ceph_inode_info *ci,
{
struct inode *inode = &ci->netfs.inode;
struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_mds_session *session = NULL;
bool need_put = false;
int mds;
- dout("ceph_flush_snaps %p\n", inode);
+ doutc(cl, "%p %llx.%llx\n", inode, ceph_vinop(inode));
if (psession)
session = *psession;
retry:
spin_lock(&ci->i_ceph_lock);
if (!(ci->i_ceph_flags & CEPH_I_FLUSH_SNAPS)) {
- dout(" no capsnap needs flush, doing nothing\n");
+ doutc(cl, " no capsnap needs flush, doing nothing\n");
goto out;
}
if (!ci->i_auth_cap) {
- dout(" no auth cap (migrating?), doing nothing\n");
+ doutc(cl, " no auth cap (migrating?), doing nothing\n");
goto out;
}
mds = ci->i_auth_cap->session->s_mds;
if (session && session->s_mds != mds) {
- dout(" oops, wrong session %p mutex\n", session);
+ doutc(cl, " oops, wrong session %p mutex\n", session);
ceph_put_mds_session(session);
session = NULL;
}
@@ -1756,21 +1798,23 @@ int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask,
struct ceph_mds_client *mdsc =
ceph_sb_to_fs_client(ci->netfs.inode.i_sb)->mdsc;
struct inode *inode = &ci->netfs.inode;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
int was = ci->i_dirty_caps;
int dirty = 0;
lockdep_assert_held(&ci->i_ceph_lock);
if (!ci->i_auth_cap) {
- pr_warn("__mark_dirty_caps %p %llx mask %s, "
- "but no auth cap (session was closed?)\n",
- inode, ceph_ino(inode), ceph_cap_string(mask));
+ pr_warn_client(cl, "%p %llx.%llx mask %s, "
+ "but no auth cap (session was closed?)\n",
+ inode, ceph_vinop(inode),
+ ceph_cap_string(mask));
return 0;
}
- dout("__mark_dirty_caps %p %s dirty %s -> %s\n", &ci->netfs.inode,
- ceph_cap_string(mask), ceph_cap_string(was),
- ceph_cap_string(was | mask));
+ doutc(cl, "%p %llx.%llx %s dirty %s -> %s\n", inode,
+ ceph_vinop(inode), ceph_cap_string(mask),
+ ceph_cap_string(was), ceph_cap_string(was | mask));
ci->i_dirty_caps |= mask;
if (was == 0) {
struct ceph_mds_session *session = ci->i_auth_cap->session;
@@ -1783,8 +1827,9 @@ int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask,
ci->i_head_snapc = ceph_get_snap_context(
ci->i_snap_realm->cached_context);
}
- dout(" inode %p now dirty snapc %p auth cap %p\n",
- &ci->netfs.inode, ci->i_head_snapc, ci->i_auth_cap);
+ doutc(cl, "%p %llx.%llx now dirty snapc %p auth cap %p\n",
+ inode, ceph_vinop(inode), ci->i_head_snapc,
+ ci->i_auth_cap);
BUG_ON(!list_empty(&ci->i_dirty_item));
spin_lock(&mdsc->cap_dirty_lock);
list_add(&ci->i_dirty_item, &session->s_cap_dirty);
@@ -1878,6 +1923,7 @@ static u64 __mark_caps_flushing(struct inode *inode,
u64 *oldest_flush_tid)
{
struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_cap_flush *cf = NULL;
int flushing;
@@ -1888,13 +1934,13 @@ static u64 __mark_caps_flushing(struct inode *inode,
BUG_ON(!ci->i_prealloc_cap_flush);
flushing = ci->i_dirty_caps;
- dout("__mark_caps_flushing flushing %s, flushing_caps %s -> %s\n",
- ceph_cap_string(flushing),
- ceph_cap_string(ci->i_flushing_caps),
- ceph_cap_string(ci->i_flushing_caps | flushing));
+ doutc(cl, "flushing %s, flushing_caps %s -> %s\n",
+ ceph_cap_string(flushing),
+ ceph_cap_string(ci->i_flushing_caps),
+ ceph_cap_string(ci->i_flushing_caps | flushing));
ci->i_flushing_caps |= flushing;
ci->i_dirty_caps = 0;
- dout(" inode %p now !dirty\n", inode);
+ doutc(cl, "%p %llx.%llx now !dirty\n", inode, ceph_vinop(inode));
swap(cf, ci->i_prealloc_cap_flush);
cf->caps = flushing;
@@ -1925,6 +1971,7 @@ static int try_nonblocking_invalidate(struct inode *inode)
__releases(ci->i_ceph_lock)
__acquires(ci->i_ceph_lock)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
u32 invalidating_gen = ci->i_rdcache_gen;
@@ -1936,12 +1983,13 @@ static int try_nonblocking_invalidate(struct inode *inode)
if (inode->i_data.nrpages == 0 &&
invalidating_gen == ci->i_rdcache_gen) {
/* success. */
- dout("try_nonblocking_invalidate %p success\n", inode);
+ doutc(cl, "%p %llx.%llx success\n", inode,
+ ceph_vinop(inode));
/* save any racing async invalidate some trouble */
ci->i_rdcache_revoking = ci->i_rdcache_gen - 1;
return 0;
}
- dout("try_nonblocking_invalidate %p failed\n", inode);
+ doutc(cl, "%p %llx.%llx failed\n", inode, ceph_vinop(inode));
return -1;
}
@@ -1973,6 +2021,7 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags)
{
struct inode *inode = &ci->netfs.inode;
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_cap *cap;
u64 flush_tid, oldest_flush_tid;
int file_wanted, used, cap_used;
@@ -2047,9 +2096,9 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags)
}
}
- dout("check_caps %llx.%llx file_want %s used %s dirty %s flushing %s"
- " issued %s revoking %s retain %s %s%s%s\n", ceph_vinop(inode),
- ceph_cap_string(file_wanted),
+ doutc(cl, "%p %llx.%llx file_want %s used %s dirty %s "
+ "flushing %s issued %s revoking %s retain %s %s%s%s\n",
+ inode, ceph_vinop(inode), ceph_cap_string(file_wanted),
ceph_cap_string(used), ceph_cap_string(ci->i_dirty_caps),
ceph_cap_string(ci->i_flushing_caps),
ceph_cap_string(issued), ceph_cap_string(revoking),
@@ -2070,10 +2119,10 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags)
(revoking & (CEPH_CAP_FILE_CACHE|
CEPH_CAP_FILE_LAZYIO)) && /* or revoking cache */
!tried_invalidate) {
- dout("check_caps trying to invalidate on %llx.%llx\n",
- ceph_vinop(inode));
+ doutc(cl, "trying to invalidate on %p %llx.%llx\n",
+ inode, ceph_vinop(inode));
if (try_nonblocking_invalidate(inode) < 0) {
- dout("check_caps queuing invalidate\n");
+ doutc(cl, "queuing invalidate\n");
queue_invalidate = true;
ci->i_rdcache_revoking = ci->i_rdcache_gen;
}
@@ -2101,35 +2150,35 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags)
cap_used &= ~ci->i_auth_cap->issued;
revoking = cap->implemented & ~cap->issued;
- dout(" mds%d cap %p used %s issued %s implemented %s revoking %s\n",
- cap->mds, cap, ceph_cap_string(cap_used),
- ceph_cap_string(cap->issued),
- ceph_cap_string(cap->implemented),
- ceph_cap_string(revoking));
+ doutc(cl, " mds%d cap %p used %s issued %s implemented %s revoking %s\n",
+ cap->mds, cap, ceph_cap_string(cap_used),
+ ceph_cap_string(cap->issued),
+ ceph_cap_string(cap->implemented),
+ ceph_cap_string(revoking));
if (cap == ci->i_auth_cap &&
(cap->issued & CEPH_CAP_FILE_WR)) {
/* request larger max_size from MDS? */
if (ci->i_wanted_max_size > ci->i_max_size &&
ci->i_wanted_max_size > ci->i_requested_max_size) {
- dout("requesting new max_size\n");
+ doutc(cl, "requesting new max_size\n");
goto ack;
}
/* approaching file_max? */
if (__ceph_should_report_size(ci)) {
- dout("i_size approaching max_size\n");
+ doutc(cl, "i_size approaching max_size\n");
goto ack;
}
}
/* flush anything dirty? */
if (cap == ci->i_auth_cap) {
if ((flags & CHECK_CAPS_FLUSH) && ci->i_dirty_caps) {
- dout("flushing dirty caps\n");
+ doutc(cl, "flushing dirty caps\n");
goto ack;
}
if (ci->i_ceph_flags & CEPH_I_FLUSH_SNAPS) {
- dout("flushing snap caps\n");
+ doutc(cl, "flushing snap caps\n");
goto ack;
}
}
@@ -2137,7 +2186,7 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags)
/* completed revocation? going down and there are no caps? */
if (revoking) {
if ((revoking & cap_used) == 0) {
- dout("completed revocation of %s\n",
+ doutc(cl, "completed revocation of %s\n",
ceph_cap_string(cap->implemented & ~cap->issued));
goto ack;
}
@@ -2315,6 +2364,7 @@ static int caps_are_flushed(struct inode *inode, u64 flush_tid)
static int flush_mdlog_and_wait_inode_unsafe_requests(struct inode *inode)
{
struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_mds_request *req1 = NULL, *req2 = NULL;
int ret, err = 0;
@@ -2404,8 +2454,9 @@ static int flush_mdlog_and_wait_inode_unsafe_requests(struct inode *inode)
kfree(sessions);
}
- dout("%s %p wait on tid %llu %llu\n", __func__,
- inode, req1 ? req1->r_tid : 0ULL, req2 ? req2->r_tid : 0ULL);
+ doutc(cl, "%p %llx.%llx wait on tid %llu %llu\n", inode,
+ ceph_vinop(inode), req1 ? req1->r_tid : 0ULL,
+ req2 ? req2->r_tid : 0ULL);
if (req1) {
ret = !wait_for_completion_timeout(&req1->r_safe_completion,
ceph_timeout_jiffies(req1->r_timeout));
@@ -2431,11 +2482,13 @@ int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync)
{
struct inode *inode = file->f_mapping->host;
struct ceph_inode_info *ci = ceph_inode(inode);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
u64 flush_tid;
int ret, err;
int dirty;
- dout("fsync %p%s\n", inode, datasync ? " datasync" : "");
+ doutc(cl, "%p %llx.%llx%s\n", inode, ceph_vinop(inode),
+ datasync ? " datasync" : "");
ret = file_write_and_wait_range(file, start, end);
if (datasync)
@@ -2446,7 +2499,7 @@ int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync)
goto out;
dirty = try_flush_caps(inode, &flush_tid);
- dout("fsync dirty caps are %s\n", ceph_cap_string(dirty));
+ doutc(cl, "dirty caps are %s\n", ceph_cap_string(dirty));
err = flush_mdlog_and_wait_inode_unsafe_requests(inode);
@@ -2467,7 +2520,8 @@ int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync)
if (err < 0)
ret = err;
out:
- dout("fsync %p%s result=%d\n", inode, datasync ? " datasync" : "", ret);
+ doutc(cl, "%p %llx.%llx%s result=%d\n", inode, ceph_vinop(inode),
+ datasync ? " datasync" : "", ret);
return ret;
}
@@ -2480,12 +2534,13 @@ int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync)
int ceph_write_inode(struct inode *inode, struct writeback_control *wbc)
{
struct ceph_inode_info *ci = ceph_inode(inode);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
u64 flush_tid;
int err = 0;
int dirty;
int wait = (wbc->sync_mode == WB_SYNC_ALL && !wbc->for_sync);
- dout("write_inode %p wait=%d\n", inode, wait);
+ doutc(cl, "%p %llx.%llx wait=%d\n", inode, ceph_vinop(inode), wait);
ceph_fscache_unpin_writeback(inode, wbc);
if (wait) {
err = ceph_wait_on_async_create(inode);
@@ -2515,6 +2570,7 @@ static void __kick_flushing_caps(struct ceph_mds_client *mdsc,
__acquires(ci->i_ceph_lock)
{
struct inode *inode = &ci->netfs.inode;
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_cap *cap;
struct ceph_cap_flush *cf;
int ret;
@@ -2540,8 +2596,8 @@ static void __kick_flushing_caps(struct ceph_mds_client *mdsc,
cap = ci->i_auth_cap;
if (!(cap && cap->session == session)) {
- pr_err("%p auth cap %p not mds%d ???\n",
- inode, cap, session->s_mds);
+ pr_err_client(cl, "%p auth cap %p not mds%d ???\n",
+ inode, cap, session->s_mds);
break;
}
@@ -2550,8 +2606,9 @@ static void __kick_flushing_caps(struct ceph_mds_client *mdsc,
if (!cf->is_capsnap) {
struct cap_msg_args arg;
- dout("kick_flushing_caps %p cap %p tid %llu %s\n",
- inode, cap, cf->tid, ceph_cap_string(cf->caps));
+ doutc(cl, "%p %llx.%llx cap %p tid %llu %s\n",
+ inode, ceph_vinop(inode), cap, cf->tid,
+ ceph_cap_string(cf->caps));
__prep_cap(&arg, cap, CEPH_CAP_OP_FLUSH,
(cf->tid < last_snap_flush ?
CEPH_CLIENT_CAPS_PENDING_CAPSNAP : 0),
@@ -2565,9 +2622,9 @@ static void __kick_flushing_caps(struct ceph_mds_client *mdsc,
struct ceph_cap_snap *capsnap =
container_of(cf, struct ceph_cap_snap,
cap_flush);
- dout("kick_flushing_caps %p capsnap %p tid %llu %s\n",
- inode, capsnap, cf->tid,
- ceph_cap_string(capsnap->dirty));
+ doutc(cl, "%p %llx.%llx capsnap %p tid %llu %s\n",
+ inode, ceph_vinop(inode), capsnap, cf->tid,
+ ceph_cap_string(capsnap->dirty));
refcount_inc(&capsnap->nref);
spin_unlock(&ci->i_ceph_lock);
@@ -2575,11 +2632,10 @@ static void __kick_flushing_caps(struct ceph_mds_client *mdsc,
ret = __send_flush_snap(inode, session, capsnap, cap->mseq,
oldest_flush_tid);
if (ret < 0) {
- pr_err("kick_flushing_caps: error sending "
- "cap flushsnap, ino (%llx.%llx) "
- "tid %llu follows %llu\n",
- ceph_vinop(inode), cf->tid,
- capsnap->follows);
+ pr_err_client(cl, "error sending cap flushsnap,"
+ " %p %llx.%llx tid %llu follows %llu\n",
+ inode, ceph_vinop(inode), cf->tid,
+ capsnap->follows);
}
ceph_put_cap_snap(capsnap);
@@ -2592,22 +2648,26 @@ static void __kick_flushing_caps(struct ceph_mds_client *mdsc,
void ceph_early_kick_flushing_caps(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_inode_info *ci;
struct ceph_cap *cap;
u64 oldest_flush_tid;
- dout("early_kick_flushing_caps mds%d\n", session->s_mds);
+ doutc(cl, "mds%d\n", session->s_mds);
spin_lock(&mdsc->cap_dirty_lock);
oldest_flush_tid = __get_oldest_flush_tid(mdsc);
spin_unlock(&mdsc->cap_dirty_lock);
list_for_each_entry(ci, &session->s_cap_flushing, i_flushing_item) {
+ struct inode *inode = &ci->netfs.inode;
+
spin_lock(&ci->i_ceph_lock);
cap = ci->i_auth_cap;
if (!(cap && cap->session == session)) {
- pr_err("%p auth cap %p not mds%d ???\n",
- &ci->netfs.inode, cap, session->s_mds);
+ pr_err_client(cl, "%p %llx.%llx auth cap %p not mds%d ???\n",
+ inode, ceph_vinop(inode), cap,
+ session->s_mds);
spin_unlock(&ci->i_ceph_lock);
continue;
}
@@ -2640,24 +2700,28 @@ void ceph_early_kick_flushing_caps(struct ceph_mds_client *mdsc,
void ceph_kick_flushing_caps(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_inode_info *ci;
struct ceph_cap *cap;
u64 oldest_flush_tid;
lockdep_assert_held(&session->s_mutex);
- dout("kick_flushing_caps mds%d\n", session->s_mds);
+ doutc(cl, "mds%d\n", session->s_mds);
spin_lock(&mdsc->cap_dirty_lock);
oldest_flush_tid = __get_oldest_flush_tid(mdsc);
spin_unlock(&mdsc->cap_dirty_lock);
list_for_each_entry(ci, &session->s_cap_flushing, i_flushing_item) {
+ struct inode *inode = &ci->netfs.inode;
+
spin_lock(&ci->i_ceph_lock);
cap = ci->i_auth_cap;
if (!(cap && cap->session == session)) {
- pr_err("%p auth cap %p not mds%d ???\n",
- &ci->netfs.inode, cap, session->s_mds);
+ pr_err_client(cl, "%p %llx.%llx auth cap %p not mds%d ???\n",
+ inode, ceph_vinop(inode), cap,
+ session->s_mds);
spin_unlock(&ci->i_ceph_lock);
continue;
}
@@ -2674,11 +2738,13 @@ void ceph_kick_flushing_inode_caps(struct ceph_mds_session *session,
{
struct ceph_mds_client *mdsc = session->s_mdsc;
struct ceph_cap *cap = ci->i_auth_cap;
+ struct inode *inode = &ci->netfs.inode;
lockdep_assert_held(&ci->i_ceph_lock);
- dout("%s %p flushing %s\n", __func__, &ci->netfs.inode,
- ceph_cap_string(ci->i_flushing_caps));
+ doutc(mdsc->fsc->client, "%p %llx.%llx flushing %s\n",
+ inode, ceph_vinop(inode),
+ ceph_cap_string(ci->i_flushing_caps));
if (!list_empty(&ci->i_cap_flush_list)) {
u64 oldest_flush_tid;
@@ -2700,6 +2766,9 @@ void ceph_kick_flushing_inode_caps(struct ceph_mds_session *session,
void ceph_take_cap_refs(struct ceph_inode_info *ci, int got,
bool snap_rwsem_locked)
{
+ struct inode *inode = &ci->netfs.inode;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
+
lockdep_assert_held(&ci->i_ceph_lock);
if (got & CEPH_CAP_PIN)
@@ -2720,10 +2789,10 @@ void ceph_take_cap_refs(struct ceph_inode_info *ci, int got,
}
if (got & CEPH_CAP_FILE_BUFFER) {
if (ci->i_wb_ref == 0)
- ihold(&ci->netfs.inode);
+ ihold(inode);
ci->i_wb_ref++;
- dout("%s %p wb %d -> %d (?)\n", __func__,
- &ci->netfs.inode, ci->i_wb_ref-1, ci->i_wb_ref);
+ doutc(cl, "%p %llx.%llx wb %d -> %d (?)\n", inode,
+ ceph_vinop(inode), ci->i_wb_ref-1, ci->i_wb_ref);
}
}
@@ -2751,19 +2820,22 @@ static int try_get_cap_refs(struct inode *inode, int need, int want,
{
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
int ret = 0;
int have, implemented;
bool snap_rwsem_locked = false;
- dout("get_cap_refs %p need %s want %s\n", inode,
- ceph_cap_string(need), ceph_cap_string(want));
+ doutc(cl, "%p %llx.%llx need %s want %s\n", inode,
+ ceph_vinop(inode), ceph_cap_string(need),
+ ceph_cap_string(want));
again:
spin_lock(&ci->i_ceph_lock);
if ((flags & CHECK_FILELOCK) &&
(ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK)) {
- dout("try_get_cap_refs %p error filelock\n", inode);
+ doutc(cl, "%p %llx.%llx error filelock\n", inode,
+ ceph_vinop(inode));
ret = -EIO;
goto out_unlock;
}
@@ -2783,8 +2855,8 @@ static int try_get_cap_refs(struct inode *inode, int need, int want,
if (have & need & CEPH_CAP_FILE_WR) {
if (endoff >= 0 && endoff > (loff_t)ci->i_max_size) {
- dout("get_cap_refs %p endoff %llu > maxsize %llu\n",
- inode, endoff, ci->i_max_size);
+ doutc(cl, "%p %llx.%llx endoff %llu > maxsize %llu\n",
+ inode, ceph_vinop(inode), endoff, ci->i_max_size);
if (endoff > ci->i_requested_max_size)
ret = ci->i_auth_cap ? -EFBIG : -EUCLEAN;
goto out_unlock;
@@ -2794,7 +2866,8 @@ static int try_get_cap_refs(struct inode *inode, int need, int want,
* can get a final snapshot value for size+mtime.
*/
if (__ceph_have_pending_cap_snap(ci)) {
- dout("get_cap_refs %p cap_snap_pending\n", inode);
+ doutc(cl, "%p %llx.%llx cap_snap_pending\n", inode,
+ ceph_vinop(inode));
goto out_unlock;
}
}
@@ -2812,9 +2885,9 @@ static int try_get_cap_refs(struct inode *inode, int need, int want,
int not = want & ~(have & need);
int revoking = implemented & ~have;
int exclude = revoking & not;
- dout("get_cap_refs %p have %s but not %s (revoking %s)\n",
- inode, ceph_cap_string(have), ceph_cap_string(not),
- ceph_cap_string(revoking));
+ doutc(cl, "%p %llx.%llx have %s but not %s (revoking %s)\n",
+ inode, ceph_vinop(inode), ceph_cap_string(have),
+ ceph_cap_string(not), ceph_cap_string(revoking));
if (!exclude || !(exclude & CEPH_CAP_FILE_BUFFER)) {
if (!snap_rwsem_locked &&
!ci->i_head_snapc &&
@@ -2854,28 +2927,31 @@ static int try_get_cap_refs(struct inode *inode, int need, int want,
spin_unlock(&s->s_cap_lock);
}
if (session_readonly) {
- dout("get_cap_refs %p need %s but mds%d readonly\n",
- inode, ceph_cap_string(need), ci->i_auth_cap->mds);
+ doutc(cl, "%p %llx.%llx need %s but mds%d readonly\n",
+ inode, ceph_vinop(inode), ceph_cap_string(need),
+ ci->i_auth_cap->mds);
ret = -EROFS;
goto out_unlock;
}
if (ceph_inode_is_shutdown(inode)) {
- dout("get_cap_refs %p inode is shutdown\n", inode);
+ doutc(cl, "%p %llx.%llx inode is shutdown\n",
+ inode, ceph_vinop(inode));
ret = -ESTALE;
goto out_unlock;
}
mds_wanted = __ceph_caps_mds_wanted(ci, false);
if (need & ~mds_wanted) {
- dout("get_cap_refs %p need %s > mds_wanted %s\n",
- inode, ceph_cap_string(need),
- ceph_cap_string(mds_wanted));
+ doutc(cl, "%p %llx.%llx need %s > mds_wanted %s\n",
+ inode, ceph_vinop(inode), ceph_cap_string(need),
+ ceph_cap_string(mds_wanted));
ret = -EUCLEAN;
goto out_unlock;
}
- dout("get_cap_refs %p have %s need %s\n", inode,
- ceph_cap_string(have), ceph_cap_string(need));
+ doutc(cl, "%p %llx.%llx have %s need %s\n", inode,
+ ceph_vinop(inode), ceph_cap_string(have),
+ ceph_cap_string(need));
}
out_unlock:
@@ -2890,8 +2966,8 @@ static int try_get_cap_refs(struct inode *inode, int need, int want,
else if (ret == 1)
ceph_update_cap_hit(&mdsc->metric);
- dout("get_cap_refs %p ret %d got %s\n", inode,
- ret, ceph_cap_string(*got));
+ doutc(cl, "%p %llx.%llx ret %d got %s\n", inode,
+ ceph_vinop(inode), ret, ceph_cap_string(*got));
return ret;
}
@@ -2903,13 +2979,14 @@ static int try_get_cap_refs(struct inode *inode, int need, int want,
static void check_max_size(struct inode *inode, loff_t endoff)
{
struct ceph_inode_info *ci = ceph_inode(inode);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
int check = 0;
/* do we need to explicitly request a larger max_size? */
spin_lock(&ci->i_ceph_lock);
if (endoff >= ci->i_max_size && endoff > ci->i_wanted_max_size) {
- dout("write %p at large endoff %llu, req max_size\n",
- inode, endoff);
+ doutc(cl, "write %p %llx.%llx at large endoff %llu, req max_size\n",
+ inode, ceph_vinop(inode), endoff);
ci->i_wanted_max_size = endoff;
}
/* duplicate ceph_check_caps()'s logic */
@@ -3119,10 +3196,12 @@ void ceph_get_cap_refs(struct ceph_inode_info *ci, int caps)
static int ceph_try_drop_cap_snap(struct ceph_inode_info *ci,
struct ceph_cap_snap *capsnap)
{
+ struct inode *inode = &ci->netfs.inode;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
+
if (!capsnap->need_flush &&
!capsnap->writing && !capsnap->dirty_pages) {
- dout("dropping cap_snap %p follows %llu\n",
- capsnap, capsnap->follows);
+ doutc(cl, "%p follows %llu\n", capsnap, capsnap->follows);
BUG_ON(capsnap->cap_flush.tid > 0);
ceph_put_snap_context(capsnap->context);
if (!list_is_last(&capsnap->ci_item, &ci->i_cap_snaps))
@@ -3154,6 +3233,7 @@ static void __ceph_put_cap_refs(struct ceph_inode_info *ci, int had,
enum put_cap_refs_mode mode)
{
struct inode *inode = &ci->netfs.inode;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
int last = 0, put = 0, flushsnaps = 0, wake = 0;
bool check_flushsnaps = false;
@@ -3176,8 +3256,8 @@ static void __ceph_put_cap_refs(struct ceph_inode_info *ci, int had,
put++;
check_flushsnaps = true;
}
- dout("put_cap_refs %p wb %d -> %d (?)\n",
- inode, ci->i_wb_ref+1, ci->i_wb_ref);
+ doutc(cl, "%p %llx.%llx wb %d -> %d (?)\n", inode,
+ ceph_vinop(inode), ci->i_wb_ref+1, ci->i_wb_ref);
}
if (had & CEPH_CAP_FILE_WR) {
if (--ci->i_wr_ref == 0) {
@@ -3217,8 +3297,8 @@ static void __ceph_put_cap_refs(struct ceph_inode_info *ci, int had,
}
spin_unlock(&ci->i_ceph_lock);
- dout("put_cap_refs %p had %s%s%s\n", inode, ceph_cap_string(had),
- last ? " last" : "", put ? " put" : "");
+ doutc(cl, "%p %llx.%llx had %s%s%s\n", inode, ceph_vinop(inode),
+ ceph_cap_string(had), last ? " last" : "", put ? " put" : "");
switch (mode) {
case PUT_CAP_REFS_SYNC:
@@ -3268,6 +3348,7 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
struct ceph_snap_context *snapc)
{
struct inode *inode = &ci->netfs.inode;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_cap_snap *capsnap = NULL, *iter;
int put = 0;
bool last = false;
@@ -3291,11 +3372,10 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
ceph_put_snap_context(ci->i_head_snapc);
ci->i_head_snapc = NULL;
}
- dout("put_wrbuffer_cap_refs on %p head %d/%d -> %d/%d %s\n",
- inode,
- ci->i_wrbuffer_ref+nr, ci->i_wrbuffer_ref_head+nr,
- ci->i_wrbuffer_ref, ci->i_wrbuffer_ref_head,
- last ? " LAST" : "");
+ doutc(cl, "on %p %llx.%llx head %d/%d -> %d/%d %s\n",
+ inode, ceph_vinop(inode), ci->i_wrbuffer_ref+nr,
+ ci->i_wrbuffer_ref_head+nr, ci->i_wrbuffer_ref,
+ ci->i_wrbuffer_ref_head, last ? " LAST" : "");
} else {
list_for_each_entry(iter, &ci->i_cap_snaps, ci_item) {
if (iter->context == snapc) {
@@ -3325,13 +3405,12 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
}
}
}
- dout("put_wrbuffer_cap_refs on %p cap_snap %p "
- " snap %lld %d/%d -> %d/%d %s%s\n",
- inode, capsnap, capsnap->context->seq,
- ci->i_wrbuffer_ref+nr, capsnap->dirty_pages + nr,
- ci->i_wrbuffer_ref, capsnap->dirty_pages,
- last ? " (wrbuffer last)" : "",
- complete_capsnap ? " (complete capsnap)" : "");
+ doutc(cl, "%p %llx.%llx cap_snap %p snap %lld %d/%d -> %d/%d %s%s\n",
+ inode, ceph_vinop(inode), capsnap, capsnap->context->seq,
+ ci->i_wrbuffer_ref+nr, capsnap->dirty_pages + nr,
+ ci->i_wrbuffer_ref, capsnap->dirty_pages,
+ last ? " (wrbuffer last)" : "",
+ complete_capsnap ? " (complete capsnap)" : "");
}
unlock:
@@ -3354,9 +3433,10 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
*/
static void invalidate_aliases(struct inode *inode)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct dentry *dn, *prev = NULL;
- dout("invalidate_aliases inode %p\n", inode);
+ doutc(cl, "%p %llx.%llx\n", inode, ceph_vinop(inode));
d_prune_aliases(inode);
/*
* For non-directory inode, d_find_alias() only returns
@@ -3415,6 +3495,7 @@ static void handle_cap_grant(struct inode *inode,
__releases(ci->i_ceph_lock)
__releases(session->s_mdsc->snap_rwsem)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
int seq = le32_to_cpu(grant->seq);
int newcaps = le32_to_cpu(grant->caps);
@@ -3438,10 +3519,11 @@ static void handle_cap_grant(struct inode *inode,
if (IS_ENCRYPTED(inode) && size)
size = extra_info->fscrypt_file_size;
- dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n",
- inode, cap, session->s_mds, seq, ceph_cap_string(newcaps));
- dout(" size %llu max_size %llu, i_size %llu\n", size, max_size,
- i_size_read(inode));
+ doutc(cl, "%p %llx.%llx cap %p mds%d seq %d %s\n", inode,
+ ceph_vinop(inode), cap, session->s_mds, seq,
+ ceph_cap_string(newcaps));
+ doutc(cl, " size %llu max_size %llu, i_size %llu\n", size,
+ max_size, i_size_read(inode));
/*
@@ -3501,15 +3583,17 @@ static void handle_cap_grant(struct inode *inode,
inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(grant->uid));
inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(grant->gid));
ci->i_btime = extra_info->btime;
- dout("%p mode 0%o uid.gid %d.%d\n", inode, inode->i_mode,
- from_kuid(&init_user_ns, inode->i_uid),
- from_kgid(&init_user_ns, inode->i_gid));
+ doutc(cl, "%p %llx.%llx mode 0%o uid.gid %d.%d\n", inode,
+ ceph_vinop(inode), inode->i_mode,
+ from_kuid(&init_user_ns, inode->i_uid),
+ from_kgid(&init_user_ns, inode->i_gid));
#if IS_ENABLED(CONFIG_FS_ENCRYPTION)
if (ci->fscrypt_auth_len != extra_info->fscrypt_auth_len ||
memcmp(ci->fscrypt_auth, extra_info->fscrypt_auth,
ci->fscrypt_auth_len))
- pr_warn_ratelimited("%s: cap grant attempt to change fscrypt_auth on non-I_NEW inode (old len %d new len %d)\n",
- __func__, ci->fscrypt_auth_len,
+ pr_warn_ratelimited_client(cl,
+ "cap grant attempt to change fscrypt_auth on non-I_NEW inode (old len %d new len %d)\n",
+ ci->fscrypt_auth_len,
extra_info->fscrypt_auth_len);
#endif
}
@@ -3527,8 +3611,8 @@ static void handle_cap_grant(struct inode *inode,
u64 version = le64_to_cpu(grant->xattr_version);
if (version > ci->i_xattrs.version) {
- dout(" got new xattrs v%llu on %p len %d\n",
- version, inode, len);
+ doutc(cl, " got new xattrs v%llu on %p %llx.%llx len %d\n",
+ version, inode, ceph_vinop(inode), len);
if (ci->i_xattrs.blob)
ceph_buffer_put(ci->i_xattrs.blob);
ci->i_xattrs.blob = ceph_buffer_get(xattr_buf);
@@ -3579,8 +3663,8 @@ static void handle_cap_grant(struct inode *inode,
if (ci->i_auth_cap == cap && (newcaps & CEPH_CAP_ANY_FILE_WR)) {
if (max_size != ci->i_max_size) {
- dout("max_size %lld -> %llu\n",
- ci->i_max_size, max_size);
+ doutc(cl, "max_size %lld -> %llu\n", ci->i_max_size,
+ max_size);
ci->i_max_size = max_size;
if (max_size >= ci->i_wanted_max_size) {
ci->i_wanted_max_size = 0; /* reset */
@@ -3594,10 +3678,9 @@ static void handle_cap_grant(struct inode *inode,
wanted = __ceph_caps_wanted(ci);
used = __ceph_caps_used(ci);
dirty = __ceph_caps_dirty(ci);
- dout(" my wanted = %s, used = %s, dirty %s\n",
- ceph_cap_string(wanted),
- ceph_cap_string(used),
- ceph_cap_string(dirty));
+ doutc(cl, " my wanted = %s, used = %s, dirty %s\n",
+ ceph_cap_string(wanted), ceph_cap_string(used),
+ ceph_cap_string(dirty));
if ((was_stale || le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) &&
(wanted & ~(cap->mds_wanted | newcaps))) {
@@ -3618,10 +3701,9 @@ static void handle_cap_grant(struct inode *inode,
if (cap->issued & ~newcaps) {
int revoking = cap->issued & ~newcaps;
- dout("revocation: %s -> %s (revoking %s)\n",
- ceph_cap_string(cap->issued),
- ceph_cap_string(newcaps),
- ceph_cap_string(revoking));
+ doutc(cl, "revocation: %s -> %s (revoking %s)\n",
+ ceph_cap_string(cap->issued), ceph_cap_string(newcaps),
+ ceph_cap_string(revoking));
if (S_ISREG(inode->i_mode) &&
(revoking & used & CEPH_CAP_FILE_BUFFER))
writeback = true; /* initiate writeback; will delay ack */
@@ -3639,11 +3721,12 @@ static void handle_cap_grant(struct inode *inode,
cap->issued = newcaps;
cap->implemented |= newcaps;
} else if (cap->issued == newcaps) {
- dout("caps unchanged: %s -> %s\n",
- ceph_cap_string(cap->issued), ceph_cap_string(newcaps));
+ doutc(cl, "caps unchanged: %s -> %s\n",
+ ceph_cap_string(cap->issued),
+ ceph_cap_string(newcaps));
} else {
- dout("grant: %s -> %s\n", ceph_cap_string(cap->issued),
- ceph_cap_string(newcaps));
+ doutc(cl, "grant: %s -> %s\n", ceph_cap_string(cap->issued),
+ ceph_cap_string(newcaps));
/* non-auth MDS is revoking the newly grant caps ? */
if (cap == ci->i_auth_cap &&
__ceph_caps_revoking_other(ci, cap, newcaps))
@@ -3732,6 +3815,7 @@ static void handle_cap_flush_ack(struct inode *inode, u64 flush_tid,
{
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_cap_flush *cf, *tmp_cf;
LIST_HEAD(to_remove);
unsigned seq = le32_to_cpu(m->seq);
@@ -3768,11 +3852,11 @@ static void handle_cap_flush_ack(struct inode *inode, u64 flush_tid,
}
}
- dout("handle_cap_flush_ack inode %p mds%d seq %d on %s cleaned %s,"
- " flushing %s -> %s\n",
- inode, session->s_mds, seq, ceph_cap_string(dirty),
- ceph_cap_string(cleaned), ceph_cap_string(ci->i_flushing_caps),
- ceph_cap_string(ci->i_flushing_caps & ~cleaned));
+ doutc(cl, "%p %llx.%llx mds%d seq %d on %s cleaned %s, flushing %s -> %s\n",
+ inode, ceph_vinop(inode), session->s_mds, seq,
+ ceph_cap_string(dirty), ceph_cap_string(cleaned),
+ ceph_cap_string(ci->i_flushing_caps),
+ ceph_cap_string(ci->i_flushing_caps & ~cleaned));
if (list_empty(&to_remove) && !cleaned)
goto out;
@@ -3788,18 +3872,21 @@ static void handle_cap_flush_ack(struct inode *inode, u64 flush_tid,
if (list_empty(&ci->i_cap_flush_list)) {
list_del_init(&ci->i_flushing_item);
if (!list_empty(&session->s_cap_flushing)) {
- dout(" mds%d still flushing cap on %p\n",
- session->s_mds,
- &list_first_entry(&session->s_cap_flushing,
- struct ceph_inode_info,
- i_flushing_item)->netfs.inode);
+ struct inode *inode =
+ &list_first_entry(&session->s_cap_flushing,
+ struct ceph_inode_info,
+ i_flushing_item)->netfs.inode;
+ doutc(cl, " mds%d still flushing cap on %p %llx.%llx\n",
+ session->s_mds, inode, ceph_vinop(inode));
}
}
mdsc->num_cap_flushing--;
- dout(" inode %p now !flushing\n", inode);
+ doutc(cl, " %p %llx.%llx now !flushing\n", inode,
+ ceph_vinop(inode));
if (ci->i_dirty_caps == 0) {
- dout(" inode %p now clean\n", inode);
+ doutc(cl, " %p %llx.%llx now clean\n", inode,
+ ceph_vinop(inode));
BUG_ON(!list_empty(&ci->i_dirty_item));
drop = true;
if (ci->i_wr_ref == 0 &&
@@ -3838,11 +3925,13 @@ void __ceph_remove_capsnap(struct inode *inode, struct ceph_cap_snap *capsnap,
{
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
+ struct ceph_client *cl = mdsc->fsc->client;
bool ret;
lockdep_assert_held(&ci->i_ceph_lock);
- dout("removing capsnap %p, inode %p ci %p\n", capsnap, inode, ci);
+ doutc(cl, "removing capsnap %p, %p %llx.%llx ci %p\n", capsnap,
+ inode, ceph_vinop(inode), ci);
list_del_init(&capsnap->ci_item);
ret = __detach_cap_flush_from_ci(ci, &capsnap->cap_flush);
@@ -3882,28 +3971,30 @@ static void handle_cap_flushsnap_ack(struct inode *inode, u64 flush_tid,
{
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
+ struct ceph_client *cl = mdsc->fsc->client;
u64 follows = le64_to_cpu(m->snap_follows);
struct ceph_cap_snap *capsnap = NULL, *iter;
bool wake_ci = false;
bool wake_mdsc = false;
- dout("handle_cap_flushsnap_ack inode %p ci %p mds%d follows %lld\n",
- inode, ci, session->s_mds, follows);
+ doutc(cl, "%p %llx.%llx ci %p mds%d follows %lld\n", inode,
+ ceph_vinop(inode), ci, session->s_mds, follows);
spin_lock(&ci->i_ceph_lock);
list_for_each_entry(iter, &ci->i_cap_snaps, ci_item) {
if (iter->follows == follows) {
if (iter->cap_flush.tid != flush_tid) {
- dout(" cap_snap %p follows %lld tid %lld !="
- " %lld\n", iter, follows,
- flush_tid, iter->cap_flush.tid);
+ doutc(cl, " cap_snap %p follows %lld "
+ "tid %lld != %lld\n", iter,
+ follows, flush_tid,
+ iter->cap_flush.tid);
break;
}
capsnap = iter;
break;
} else {
- dout(" skipping cap_snap %p follows %lld\n",
- iter, iter->follows);
+ doutc(cl, " skipping cap_snap %p follows %lld\n",
+ iter, iter->follows);
}
}
if (capsnap)
@@ -3932,6 +4023,7 @@ static bool handle_cap_trunc(struct inode *inode,
struct cap_extra_info *extra_info)
{
struct ceph_inode_info *ci = ceph_inode(inode);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
int mds = session->s_mds;
int seq = le32_to_cpu(trunc->seq);
u32 truncate_seq = le32_to_cpu(trunc->truncate_seq);
@@ -3954,8 +4046,8 @@ static bool handle_cap_trunc(struct inode *inode,
if (IS_ENCRYPTED(inode) && size)
size = extra_info->fscrypt_file_size;
- dout("%s inode %p mds%d seq %d to %lld truncate seq %d\n",
- __func__, inode, mds, seq, truncate_size, truncate_seq);
+ doutc(cl, "%p %llx.%llx mds%d seq %d to %lld truncate seq %d\n",
+ inode, ceph_vinop(inode), mds, seq, truncate_size, truncate_seq);
queue_trunc = ceph_fill_file_size(inode, issued,
truncate_seq, truncate_size, size);
return queue_trunc;
@@ -3974,6 +4066,7 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex,
struct ceph_mds_session *session)
{
struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc;
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mds_session *tsession = NULL;
struct ceph_cap *cap, *tcap, *new_cap = NULL;
struct ceph_inode_info *ci = ceph_inode(inode);
@@ -3993,8 +4086,8 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex,
target = -1;
}
- dout("handle_cap_export inode %p ci %p mds%d mseq %d target %d\n",
- inode, ci, mds, mseq, target);
+ doutc(cl, "%p %llx.%llx ci %p mds%d mseq %d target %d\n",
+ inode, ceph_vinop(inode), ci, mds, mseq, target);
retry:
down_read(&mdsc->snap_rwsem);
spin_lock(&ci->i_ceph_lock);
@@ -4014,12 +4107,13 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex,
issued = cap->issued;
if (issued != cap->implemented)
- pr_err_ratelimited("handle_cap_export: issued != implemented: "
- "ino (%llx.%llx) mds%d seq %d mseq %d "
- "issued %s implemented %s\n",
- ceph_vinop(inode), mds, cap->seq, cap->mseq,
- ceph_cap_string(issued),
- ceph_cap_string(cap->implemented));
+ pr_err_ratelimited_client(cl, "issued != implemented: "
+ "%p %llx.%llx mds%d seq %d mseq %d"
+ " issued %s implemented %s\n",
+ inode, ceph_vinop(inode), mds,
+ cap->seq, cap->mseq,
+ ceph_cap_string(issued),
+ ceph_cap_string(cap->implemented));
tcap = __get_cap_for_mds(ci, target);
@@ -4027,7 +4121,8 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex,
/* already have caps from the target */
if (tcap->cap_id == t_cap_id &&
ceph_seq_cmp(tcap->seq, t_seq) < 0) {
- dout(" updating import cap %p mds%d\n", tcap, target);
+ doutc(cl, " updating import cap %p mds%d\n", tcap,
+ target);
tcap->cap_id = t_cap_id;
tcap->seq = t_seq - 1;
tcap->issue_seq = t_seq - 1;
@@ -4108,6 +4203,7 @@ static void handle_cap_import(struct ceph_mds_client *mdsc,
struct ceph_cap **target_cap, int *old_issued)
{
struct ceph_inode_info *ci = ceph_inode(inode);
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_cap *cap, *ocap, *new_cap = NULL;
int mds = session->s_mds;
int issued;
@@ -4128,8 +4224,8 @@ static void handle_cap_import(struct ceph_mds_client *mdsc,
peer = -1;
}
- dout("handle_cap_import inode %p ci %p mds%d mseq %d peer %d\n",
- inode, ci, mds, mseq, peer);
+ doutc(cl, "%p %llx.%llx ci %p mds%d mseq %d peer %d\n",
+ inode, ceph_vinop(inode), ci, mds, mseq, peer);
retry:
cap = __get_cap_for_mds(ci, mds);
if (!cap) {
@@ -4155,17 +4251,17 @@ static void handle_cap_import(struct ceph_mds_client *mdsc,
ocap = peer >= 0 ? __get_cap_for_mds(ci, peer) : NULL;
if (ocap && ocap->cap_id == p_cap_id) {
- dout(" remove export cap %p mds%d flags %d\n",
- ocap, peer, ph->flags);
+ doutc(cl, " remove export cap %p mds%d flags %d\n",
+ ocap, peer, ph->flags);
if ((ph->flags & CEPH_CAP_FLAG_AUTH) &&
(ocap->seq != le32_to_cpu(ph->seq) ||
ocap->mseq != le32_to_cpu(ph->mseq))) {
- pr_err_ratelimited("handle_cap_import: "
- "mismatched seq/mseq: ino (%llx.%llx) "
- "mds%d seq %d mseq %d importer mds%d "
- "has peer seq %d mseq %d\n",
- ceph_vinop(inode), peer, ocap->seq,
- ocap->mseq, mds, le32_to_cpu(ph->seq),
+ pr_err_ratelimited_client(cl, "mismatched seq/mseq: "
+ "%p %llx.%llx mds%d seq %d mseq %d"
+ " importer mds%d has peer seq %d mseq %d\n",
+ inode, ceph_vinop(inode), peer,
+ ocap->seq, ocap->mseq, mds,
+ le32_to_cpu(ph->seq),
le32_to_cpu(ph->mseq));
}
ceph_remove_cap(mdsc, ocap, (ph->flags & CEPH_CAP_FLAG_RELEASE));
@@ -4231,6 +4327,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
struct ceph_msg *msg)
{
struct ceph_mds_client *mdsc = session->s_mdsc;
+ struct ceph_client *cl = mdsc->fsc->client;
struct inode *inode;
struct ceph_inode_info *ci;
struct ceph_cap *cap;
@@ -4249,7 +4346,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
bool close_sessions = false;
bool do_cap_release = false;
- dout("handle_caps from mds%d\n", session->s_mds);
+ doutc(cl, "from mds%d\n", session->s_mds);
if (!ceph_inc_mds_stopping_blocker(mdsc, session))
return;
@@ -4352,15 +4449,15 @@ void ceph_handle_caps(struct ceph_mds_session *session,
/* lookup ino */
inode = ceph_find_inode(mdsc->fsc->sb, vino);
- dout(" op %s ino %llx.%llx inode %p\n", ceph_cap_op_name(op), vino.ino,
- vino.snap, inode);
+ doutc(cl, " op %s ino %llx.%llx inode %p\n", ceph_cap_op_name(op),
+ vino.ino, vino.snap, inode);
mutex_lock(&session->s_mutex);
- dout(" mds%d seq %lld cap seq %u\n", session->s_mds, session->s_seq,
- (unsigned)seq);
+ doutc(cl, " mds%d seq %lld cap seq %u\n", session->s_mds,
+ session->s_seq, (unsigned)seq);
if (!inode) {
- dout(" i don't have ino %llx\n", vino.ino);
+ doutc(cl, " i don't have ino %llx\n", vino.ino);
switch (op) {
case CEPH_CAP_OP_IMPORT:
@@ -4415,9 +4512,9 @@ void ceph_handle_caps(struct ceph_mds_session *session,
spin_lock(&ci->i_ceph_lock);
cap = __get_cap_for_mds(ceph_inode(inode), session->s_mds);
if (!cap) {
- dout(" no cap on %p ino %llx.%llx from mds%d\n",
- inode, ceph_ino(inode), ceph_snap(inode),
- session->s_mds);
+ doutc(cl, " no cap on %p ino %llx.%llx from mds%d\n",
+ inode, ceph_ino(inode), ceph_snap(inode),
+ session->s_mds);
spin_unlock(&ci->i_ceph_lock);
switch (op) {
case CEPH_CAP_OP_REVOKE:
@@ -4455,8 +4552,8 @@ void ceph_handle_caps(struct ceph_mds_session *session,
default:
spin_unlock(&ci->i_ceph_lock);
- pr_err("ceph_handle_caps: unknown cap op %d %s\n", op,
- ceph_cap_op_name(op));
+ pr_err_client(cl, "unknown cap op %d %s\n", op,
+ ceph_cap_op_name(op));
}
done:
@@ -4497,7 +4594,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
goto done;
bad:
- pr_err("ceph_handle_caps: corrupt message\n");
+ pr_err_client(cl, "corrupt message\n");
ceph_msg_dump(msg);
goto out;
}
@@ -4511,6 +4608,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
*/
unsigned long ceph_check_delayed_caps(struct ceph_mds_client *mdsc)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct inode *inode;
struct ceph_inode_info *ci;
struct ceph_mount_options *opt = mdsc->fsc->mount_options;
@@ -4518,14 +4616,14 @@ unsigned long ceph_check_delayed_caps(struct ceph_mds_client *mdsc)
unsigned long loop_start = jiffies;
unsigned long delay = 0;
- dout("check_delayed_caps\n");
+ doutc(cl, "begin\n");
spin_lock(&mdsc->cap_delay_lock);
while (!list_empty(&mdsc->cap_delay_list)) {
ci = list_first_entry(&mdsc->cap_delay_list,
struct ceph_inode_info,
i_cap_delay_list);
if (time_before(loop_start, ci->i_hold_caps_max - delay_max)) {
- dout("%s caps added recently. Exiting loop", __func__);
+ doutc(cl, "caps added recently. Exiting loop");
delay = ci->i_hold_caps_max;
break;
}
@@ -4537,13 +4635,15 @@ unsigned long ceph_check_delayed_caps(struct ceph_mds_client *mdsc)
inode = igrab(&ci->netfs.inode);
if (inode) {
spin_unlock(&mdsc->cap_delay_lock);
- dout("check_delayed_caps on %p\n", inode);
+ doutc(cl, "on %p %llx.%llx\n", inode,
+ ceph_vinop(inode));
ceph_check_caps(ci, 0);
iput(inode);
spin_lock(&mdsc->cap_delay_lock);
}
}
spin_unlock(&mdsc->cap_delay_lock);
+ doutc(cl, "done\n");
return delay;
}
@@ -4554,17 +4654,18 @@ unsigned long ceph_check_delayed_caps(struct ceph_mds_client *mdsc)
static void flush_dirty_session_caps(struct ceph_mds_session *s)
{
struct ceph_mds_client *mdsc = s->s_mdsc;
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_inode_info *ci;
struct inode *inode;
- dout("flush_dirty_caps\n");
+ doutc(cl, "begin\n");
spin_lock(&mdsc->cap_dirty_lock);
while (!list_empty(&s->s_cap_dirty)) {
ci = list_first_entry(&s->s_cap_dirty, struct ceph_inode_info,
i_dirty_item);
inode = &ci->netfs.inode;
ihold(inode);
- dout("flush_dirty_caps %llx.%llx\n", ceph_vinop(inode));
+ doutc(cl, "%p %llx.%llx\n", inode, ceph_vinop(inode));
spin_unlock(&mdsc->cap_dirty_lock);
ceph_wait_on_async_create(inode);
ceph_check_caps(ci, CHECK_CAPS_FLUSH);
@@ -4572,7 +4673,7 @@ static void flush_dirty_session_caps(struct ceph_mds_session *s)
spin_lock(&mdsc->cap_dirty_lock);
}
spin_unlock(&mdsc->cap_dirty_lock);
- dout("flush_dirty_caps done\n");
+ doutc(cl, "done\n");
}
void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc)
@@ -4697,6 +4798,7 @@ int ceph_encode_inode_release(void **p, struct inode *inode,
int mds, int drop, int unless, int force)
{
struct ceph_inode_info *ci = ceph_inode(inode);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_cap *cap;
struct ceph_mds_request_release *rel = *p;
int used, dirty;
@@ -4706,9 +4808,9 @@ int ceph_encode_inode_release(void **p, struct inode *inode,
used = __ceph_caps_used(ci);
dirty = __ceph_caps_dirty(ci);
- dout("encode_inode_release %p mds%d used|dirty %s drop %s unless %s\n",
- inode, mds, ceph_cap_string(used|dirty), ceph_cap_string(drop),
- ceph_cap_string(unless));
+ doutc(cl, "%p %llx.%llx mds%d used|dirty %s drop %s unless %s\n",
+ inode, ceph_vinop(inode), mds, ceph_cap_string(used|dirty),
+ ceph_cap_string(drop), ceph_cap_string(unless));
/* only drop unused, clean caps */
drop &= ~(used | dirty);
@@ -4730,12 +4832,13 @@ int ceph_encode_inode_release(void **p, struct inode *inode,
if (force || (cap->issued & drop)) {
if (cap->issued & drop) {
int wanted = __ceph_caps_wanted(ci);
- dout("encode_inode_release %p cap %p "
- "%s -> %s, wanted %s -> %s\n", inode, cap,
- ceph_cap_string(cap->issued),
- ceph_cap_string(cap->issued & ~drop),
- ceph_cap_string(cap->mds_wanted),
- ceph_cap_string(wanted));
+ doutc(cl, "%p %llx.%llx cap %p %s -> %s, "
+ "wanted %s -> %s\n", inode,
+ ceph_vinop(inode), cap,
+ ceph_cap_string(cap->issued),
+ ceph_cap_string(cap->issued & ~drop),
+ ceph_cap_string(cap->mds_wanted),
+ ceph_cap_string(wanted));
cap->issued &= ~drop;
cap->implemented &= ~drop;
@@ -4744,9 +4847,9 @@ int ceph_encode_inode_release(void **p, struct inode *inode,
!(wanted & CEPH_CAP_ANY_FILE_WR))
ci->i_requested_max_size = 0;
} else {
- dout("encode_inode_release %p cap %p %s"
- " (force)\n", inode, cap,
- ceph_cap_string(cap->issued));
+ doutc(cl, "%p %llx.%llx cap %p %s (force)\n",
+ inode, ceph_vinop(inode), cap,
+ ceph_cap_string(cap->issued));
}
rel->ino = cpu_to_le64(ceph_ino(inode));
@@ -4761,8 +4864,9 @@ int ceph_encode_inode_release(void **p, struct inode *inode,
*p += sizeof(*rel);
ret = 1;
} else {
- dout("encode_inode_release %p cap %p %s (noop)\n",
- inode, cap, ceph_cap_string(cap->issued));
+ doutc(cl, "%p %llx.%llx cap %p %s (noop)\n",
+ inode, ceph_vinop(inode), cap,
+ ceph_cap_string(cap->issued));
}
}
spin_unlock(&ci->i_ceph_lock);
@@ -4787,6 +4891,7 @@ int ceph_encode_dentry_release(void **p, struct dentry *dentry,
{
struct ceph_mds_request_release *rel = *p;
struct ceph_dentry_info *di = ceph_dentry(dentry);
+ struct ceph_client *cl;
int force = 0;
int ret;
@@ -4806,10 +4911,11 @@ int ceph_encode_dentry_release(void **p, struct dentry *dentry,
ret = ceph_encode_inode_release(p, dir, mds, drop, unless, force);
+ cl = ceph_inode_to_client(dir);
spin_lock(&dentry->d_lock);
if (ret && di->lease_session && di->lease_session->s_mds == mds) {
- dout("encode_dentry_release %p mds%d seq %d\n",
- dentry, mds, (int)di->lease_seq);
+ doutc(cl, "%p mds%d seq %d\n", dentry, mds,
+ (int)di->lease_seq);
rel->dname_seq = cpu_to_le32(di->lease_seq);
__ceph_mdsc_drop_dentry_lease(dentry);
spin_unlock(&dentry->d_lock);
@@ -4835,12 +4941,14 @@ int ceph_encode_dentry_release(void **p, struct dentry *dentry,
static int remove_capsnaps(struct ceph_mds_client *mdsc, struct inode *inode)
{
struct ceph_inode_info *ci = ceph_inode(inode);
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_cap_snap *capsnap;
int capsnap_release = 0;
lockdep_assert_held(&ci->i_ceph_lock);
- dout("removing capsnaps, ci is %p, inode is %p\n", ci, inode);
+ doutc(cl, "removing capsnaps, ci is %p, %p %llx.%llx\n",
+ ci, inode, ceph_vinop(inode));
while (!list_empty(&ci->i_cap_snaps)) {
capsnap = list_first_entry(&ci->i_cap_snaps,
@@ -4859,6 +4967,7 @@ int ceph_purge_inode_cap(struct inode *inode, struct ceph_cap *cap, bool *invali
{
struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
struct ceph_mds_client *mdsc = fsc->mdsc;
+ struct ceph_client *cl = fsc->client;
struct ceph_inode_info *ci = ceph_inode(inode);
bool is_auth;
bool dirty_dropped = false;
@@ -4866,8 +4975,8 @@ int ceph_purge_inode_cap(struct inode *inode, struct ceph_cap *cap, bool *invali
lockdep_assert_held(&ci->i_ceph_lock);
- dout("removing cap %p, ci is %p, inode is %p\n",
- cap, ci, &ci->netfs.inode);
+ doutc(cl, "removing cap %p, ci is %p, %p %llx.%llx\n",
+ cap, ci, inode, ceph_vinop(inode));
is_auth = (cap == ci->i_auth_cap);
__ceph_remove_cap(cap, false);
@@ -4894,19 +5003,19 @@ int ceph_purge_inode_cap(struct inode *inode, struct ceph_cap *cap, bool *invali
}
if (!list_empty(&ci->i_dirty_item)) {
- pr_warn_ratelimited(
- " dropping dirty %s state for %p %lld\n",
+ pr_warn_ratelimited_client(cl,
+ " dropping dirty %s state for %p %llx.%llx\n",
ceph_cap_string(ci->i_dirty_caps),
- inode, ceph_ino(inode));
+ inode, ceph_vinop(inode));
ci->i_dirty_caps = 0;
list_del_init(&ci->i_dirty_item);
dirty_dropped = true;
}
if (!list_empty(&ci->i_flushing_item)) {
- pr_warn_ratelimited(
- " dropping dirty+flushing %s state for %p %lld\n",
+ pr_warn_ratelimited_client(cl,
+ " dropping dirty+flushing %s state for %p %llx.%llx\n",
ceph_cap_string(ci->i_flushing_caps),
- inode, ceph_ino(inode));
+ inode, ceph_vinop(inode));
ci->i_flushing_caps = 0;
list_del_init(&ci->i_flushing_item);
mdsc->num_cap_flushing--;
@@ -4929,8 +5038,9 @@ int ceph_purge_inode_cap(struct inode *inode, struct ceph_cap *cap, bool *invali
if (atomic_read(&ci->i_filelock_ref) > 0) {
/* make further file lock syscall return -EIO */
ci->i_ceph_flags |= CEPH_I_ERROR_FILELOCK;
- pr_warn_ratelimited(" dropping file locks for %p %lld\n",
- inode, ceph_ino(inode));
+ pr_warn_ratelimited_client(cl,
+ " dropping file locks for %p %llx.%llx\n",
+ inode, ceph_vinop(inode));
}
if (!ci->i_dirty_caps && ci->i_prealloc_cap_flush) {
diff --git a/fs/ceph/crypto.c b/fs/ceph/crypto.c
index 08c385610731..d692ebfddedb 100644
--- a/fs/ceph/crypto.c
+++ b/fs/ceph/crypto.c
@@ -211,6 +211,7 @@ void ceph_fscrypt_as_ctx_to_req(struct ceph_mds_request *req,
static struct inode *parse_longname(const struct inode *parent,
const char *name, int *name_len)
{
+ struct ceph_client *cl = ceph_inode_to_client(parent);
struct inode *dir = NULL;
struct ceph_vino vino = { .snap = CEPH_NOSNAP };
char *inode_number;
@@ -222,12 +223,12 @@ static struct inode *parse_longname(const struct inode *parent,
name++;
name_end = strrchr(name, '_');
if (!name_end) {
- dout("Failed to parse long snapshot name: %s\n", name);
+ doutc(cl, "failed to parse long snapshot name: %s\n", name);
return ERR_PTR(-EIO);
}
*name_len = (name_end - name);
if (*name_len <= 0) {
- pr_err("Failed to parse long snapshot name\n");
+ pr_err_client(cl, "failed to parse long snapshot name\n");
return ERR_PTR(-EIO);
}
@@ -239,7 +240,7 @@ static struct inode *parse_longname(const struct inode *parent,
return ERR_PTR(-ENOMEM);
ret = kstrtou64(inode_number, 10, &vino.ino);
if (ret) {
- dout("Failed to parse inode number: %s\n", name);
+ doutc(cl, "failed to parse inode number: %s\n", name);
dir = ERR_PTR(ret);
goto out;
}
@@ -250,7 +251,7 @@ static struct inode *parse_longname(const struct inode *parent,
/* This can happen if we're not mounting cephfs on the root */
dir = ceph_get_inode(parent->i_sb, vino, NULL);
if (IS_ERR(dir))
- dout("Can't find inode %s (%s)\n", inode_number, name);
+ doutc(cl, "can't find inode %s (%s)\n", inode_number, name);
}
out:
@@ -261,6 +262,7 @@ static struct inode *parse_longname(const struct inode *parent,
int ceph_encode_encrypted_dname(struct inode *parent, struct qstr *d_name,
char *buf)
{
+ struct ceph_client *cl = ceph_inode_to_client(parent);
struct inode *dir = parent;
struct qstr iname;
u32 len;
@@ -329,7 +331,7 @@ int ceph_encode_encrypted_dname(struct inode *parent, struct qstr *d_name,
/* base64 encode the encrypted name */
elen = ceph_base64_encode(cryptbuf, len, buf);
- dout("base64-encoded ciphertext name = %.*s\n", elen, buf);
+ doutc(cl, "base64-encoded ciphertext name = %.*s\n", elen, buf);
/* To understand the 240 limit, see CEPH_NOHASH_NAME_MAX comments */
WARN_ON(elen > 240);
@@ -504,7 +506,10 @@ int ceph_fscrypt_decrypt_block_inplace(const struct inode *inode,
struct page *page, unsigned int len,
unsigned int offs, u64 lblk_num)
{
- dout("%s: len %u offs %u blk %llu\n", __func__, len, offs, lblk_num);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
+
+ doutc(cl, "%p %llx.%llx len %u offs %u blk %llu\n", inode,
+ ceph_vinop(inode), len, offs, lblk_num);
return fscrypt_decrypt_block_inplace(inode, page, len, offs, lblk_num);
}
@@ -513,7 +518,10 @@ int ceph_fscrypt_encrypt_block_inplace(const struct inode *inode,
unsigned int offs, u64 lblk_num,
gfp_t gfp_flags)
{
- dout("%s: len %u offs %u blk %llu\n", __func__, len, offs, lblk_num);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
+
+ doutc(cl, "%p %llx.%llx len %u offs %u blk %llu\n", inode,
+ ceph_vinop(inode), len, offs, lblk_num);
return fscrypt_encrypt_block_inplace(inode, page, len, offs, lblk_num,
gfp_flags);
}
@@ -582,6 +590,7 @@ int ceph_fscrypt_decrypt_extents(struct inode *inode, struct page **page,
u64 off, struct ceph_sparse_extent *map,
u32 ext_cnt)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
int i, ret = 0;
struct ceph_inode_info *ci = ceph_inode(inode);
u64 objno, objoff;
@@ -589,7 +598,8 @@ int ceph_fscrypt_decrypt_extents(struct inode *inode, struct page **page,
/* Nothing to do for empty array */
if (ext_cnt == 0) {
- dout("%s: empty array, ret 0\n", __func__);
+ doutc(cl, "%p %llx.%llx empty array, ret 0\n", inode,
+ ceph_vinop(inode));
return 0;
}
@@ -603,14 +613,17 @@ int ceph_fscrypt_decrypt_extents(struct inode *inode, struct page **page,
int fret;
if ((ext->off | ext->len) & ~CEPH_FSCRYPT_BLOCK_MASK) {
- pr_warn("%s: bad encrypted sparse extent idx %d off %llx len %llx\n",
- __func__, i, ext->off, ext->len);
+ pr_warn_client(cl,
+ "%p %llx.%llx bad encrypted sparse extent "
+ "idx %d off %llx len %llx\n",
+ inode, ceph_vinop(inode), i, ext->off,
+ ext->len);
return -EIO;
}
fret = ceph_fscrypt_decrypt_pages(inode, &page[pgidx],
off + pgsoff, ext->len);
- dout("%s: [%d] 0x%llx~0x%llx fret %d\n", __func__, i,
- ext->off, ext->len, fret);
+ doutc(cl, "%p %llx.%llx [%d] 0x%llx~0x%llx fret %d\n", inode,
+ ceph_vinop(inode), i, ext->off, ext->len, fret);
if (fret < 0) {
if (ret == 0)
ret = fret;
@@ -618,7 +631,7 @@ int ceph_fscrypt_decrypt_extents(struct inode *inode, struct page **page,
}
ret = pgsoff + fret;
}
- dout("%s: ret %d\n", __func__, ret);
+ doutc(cl, "ret %d\n", ret);
return ret;
}
diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c
index 2f1e7498cd74..24c08078f5aa 100644
--- a/fs/ceph/debugfs.c
+++ b/fs/ceph/debugfs.c
@@ -398,7 +398,7 @@ DEFINE_SIMPLE_ATTRIBUTE(congestion_kb_fops, congestion_kb_get,
void ceph_fs_debugfs_cleanup(struct ceph_fs_client *fsc)
{
- dout("ceph_fs_debugfs_cleanup\n");
+ doutc(fsc->client, "begin\n");
debugfs_remove(fsc->debugfs_bdi);
debugfs_remove(fsc->debugfs_congestion_kb);
debugfs_remove(fsc->debugfs_mdsmap);
@@ -407,13 +407,14 @@ void ceph_fs_debugfs_cleanup(struct ceph_fs_client *fsc)
debugfs_remove(fsc->debugfs_status);
debugfs_remove(fsc->debugfs_mdsc);
debugfs_remove_recursive(fsc->debugfs_metrics_dir);
+ doutc(fsc->client, "done\n");
}
void ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
{
char name[100];
- dout("ceph_fs_debugfs_init\n");
+ doutc(fsc->client, "begin\n");
fsc->debugfs_congestion_kb =
debugfs_create_file("writeback_congestion_kb",
0600,
@@ -469,6 +470,7 @@ void ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
&metrics_size_fops);
debugfs_create_file("caps", 0400, fsc->debugfs_metrics_dir, fsc,
&metrics_caps_fops);
+ doutc(fsc->client, "done\n");
}
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index d3bb28939194..0b764dcbc7bf 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -109,7 +109,9 @@ static int fpos_cmp(loff_t l, loff_t r)
* regardless of what dir changes take place on the
* server.
*/
-static int note_last_dentry(struct ceph_dir_file_info *dfi, const char *name,
+static int note_last_dentry(struct ceph_fs_client *fsc,
+ struct ceph_dir_file_info *dfi,
+ const char *name,
int len, unsigned next_offset)
{
char *buf = kmalloc(len+1, GFP_KERNEL);
@@ -120,7 +122,7 @@ static int note_last_dentry(struct ceph_dir_file_info *dfi, const char *name,
memcpy(dfi->last_name, name, len);
dfi->last_name[len] = 0;
dfi->next_offset = next_offset;
- dout("note_last_dentry '%s'\n", dfi->last_name);
+ doutc(fsc->client, "'%s'\n", dfi->last_name);
return 0;
}
@@ -130,6 +132,7 @@ __dcache_find_get_entry(struct dentry *parent, u64 idx,
struct ceph_readdir_cache_control *cache_ctl)
{
struct inode *dir = d_inode(parent);
+ struct ceph_client *cl = ceph_inode_to_client(dir);
struct dentry *dentry;
unsigned idx_mask = (PAGE_SIZE / sizeof(struct dentry *)) - 1;
loff_t ptr_pos = idx * sizeof(struct dentry *);
@@ -142,7 +145,7 @@ __dcache_find_get_entry(struct dentry *parent, u64 idx,
ceph_readdir_cache_release(cache_ctl);
cache_ctl->page = find_lock_page(&dir->i_data, ptr_pgoff);
if (!cache_ctl->page) {
- dout(" page %lu not found\n", ptr_pgoff);
+ doutc(cl, " page %lu not found\n", ptr_pgoff);
return ERR_PTR(-EAGAIN);
}
/* reading/filling the cache are serialized by
@@ -185,13 +188,16 @@ static int __dcache_readdir(struct file *file, struct dir_context *ctx,
struct ceph_dir_file_info *dfi = file->private_data;
struct dentry *parent = file->f_path.dentry;
struct inode *dir = d_inode(parent);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(dir);
+ struct ceph_client *cl = ceph_inode_to_client(dir);
struct dentry *dentry, *last = NULL;
struct ceph_dentry_info *di;
struct ceph_readdir_cache_control cache_ctl = {};
u64 idx = 0;
int err = 0;
- dout("__dcache_readdir %p v%u at %llx\n", dir, (unsigned)shared_gen, ctx->pos);
+ doutc(cl, "%p %llx.%llx v%u at %llx\n", dir, ceph_vinop(dir),
+ (unsigned)shared_gen, ctx->pos);
/* search start position */
if (ctx->pos > 2) {
@@ -221,7 +227,8 @@ static int __dcache_readdir(struct file *file, struct dir_context *ctx,
dput(dentry);
}
- dout("__dcache_readdir %p cache idx %llu\n", dir, idx);
+ doutc(cl, "%p %llx.%llx cache idx %llu\n", dir,
+ ceph_vinop(dir), idx);
}
@@ -257,8 +264,8 @@ static int __dcache_readdir(struct file *file, struct dir_context *ctx,
spin_unlock(&dentry->d_lock);
if (emit_dentry) {
- dout(" %llx dentry %p %pd %p\n", di->offset,
- dentry, dentry, d_inode(dentry));
+ doutc(cl, " %llx dentry %p %pd %p\n", di->offset,
+ dentry, dentry, d_inode(dentry));
ctx->pos = di->offset;
if (!dir_emit(ctx, dentry->d_name.name,
dentry->d_name.len, ceph_present_inode(d_inode(dentry)),
@@ -281,7 +288,8 @@ static int __dcache_readdir(struct file *file, struct dir_context *ctx,
if (last) {
int ret;
di = ceph_dentry(last);
- ret = note_last_dentry(dfi, last->d_name.name, last->d_name.len,
+ ret = note_last_dentry(fsc, dfi, last->d_name.name,
+ last->d_name.len,
fpos_off(di->offset) + 1);
if (ret < 0)
err = ret;
@@ -312,18 +320,21 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
struct ceph_mds_client *mdsc = fsc->mdsc;
+ struct ceph_client *cl = fsc->client;
int i;
int err;
unsigned frag = -1;
struct ceph_mds_reply_info_parsed *rinfo;
- dout("readdir %p file %p pos %llx\n", inode, file, ctx->pos);
+ doutc(cl, "%p %llx.%llx file %p pos %llx\n", inode,
+ ceph_vinop(inode), file, ctx->pos);
if (dfi->file_info.flags & CEPH_F_ATEND)
return 0;
/* always start with . and .. */
if (ctx->pos == 0) {
- dout("readdir off 0 -> '.'\n");
+ doutc(cl, "%p %llx.%llx off 0 -> '.'\n", inode,
+ ceph_vinop(inode));
if (!dir_emit(ctx, ".", 1, ceph_present_inode(inode),
inode->i_mode >> 12))
return 0;
@@ -337,7 +348,8 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
ino = ceph_present_inode(dentry->d_parent->d_inode);
spin_unlock(&dentry->d_lock);
- dout("readdir off 1 -> '..'\n");
+ doutc(cl, "%p %llx.%llx off 1 -> '..'\n", inode,
+ ceph_vinop(inode));
if (!dir_emit(ctx, "..", 2, ino, inode->i_mode >> 12))
return 0;
ctx->pos = 2;
@@ -391,8 +403,8 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
frag = fpos_frag(ctx->pos);
}
- dout("readdir fetching %llx.%llx frag %x offset '%s'\n",
- ceph_vinop(inode), frag, dfi->last_name);
+ doutc(cl, "fetching %p %llx.%llx frag %x offset '%s'\n",
+ inode, ceph_vinop(inode), frag, dfi->last_name);
req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS);
if (IS_ERR(req))
return PTR_ERR(req);
@@ -446,12 +458,12 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
ceph_mdsc_put_request(req);
return err;
}
- dout("readdir got and parsed readdir result=%d on "
- "frag %x, end=%d, complete=%d, hash_order=%d\n",
- err, frag,
- (int)req->r_reply_info.dir_end,
- (int)req->r_reply_info.dir_complete,
- (int)req->r_reply_info.hash_order);
+ doutc(cl, "%p %llx.%llx got and parsed readdir result=%d"
+ "on frag %x, end=%d, complete=%d, hash_order=%d\n",
+ inode, ceph_vinop(inode), err, frag,
+ (int)req->r_reply_info.dir_end,
+ (int)req->r_reply_info.dir_complete,
+ (int)req->r_reply_info.hash_order);
rinfo = &req->r_reply_info;
if (le32_to_cpu(rinfo->dir_dir->frag) != frag) {
@@ -481,7 +493,8 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
dfi->dir_ordered_count = req->r_dir_ordered_cnt;
}
} else {
- dout("readdir !did_prepopulate\n");
+ doutc(cl, "%p %llx.%llx !did_prepopulate\n", inode,
+ ceph_vinop(inode));
/* disable readdir cache */
dfi->readdir_cache_idx = -1;
/* preclude from marking dir complete */
@@ -494,8 +507,8 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
rinfo->dir_entries + (rinfo->dir_nr-1);
unsigned next_offset = req->r_reply_info.dir_end ?
2 : (fpos_off(rde->offset) + 1);
- err = note_last_dentry(dfi, rde->name, rde->name_len,
- next_offset);
+ err = note_last_dentry(fsc, dfi, rde->name,
+ rde->name_len, next_offset);
if (err) {
ceph_mdsc_put_request(dfi->last_readdir);
dfi->last_readdir = NULL;
@@ -508,9 +521,9 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
}
rinfo = &dfi->last_readdir->r_reply_info;
- dout("readdir frag %x num %d pos %llx chunk first %llx\n",
- dfi->frag, rinfo->dir_nr, ctx->pos,
- rinfo->dir_nr ? rinfo->dir_entries[0].offset : 0LL);
+ doutc(cl, "%p %llx.%llx frag %x num %d pos %llx chunk first %llx\n",
+ inode, ceph_vinop(inode), dfi->frag, rinfo->dir_nr, ctx->pos,
+ rinfo->dir_nr ? rinfo->dir_entries[0].offset : 0LL);
i = 0;
/* search start position */
@@ -530,18 +543,24 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
struct ceph_mds_reply_dir_entry *rde = rinfo->dir_entries + i;
if (rde->offset < ctx->pos) {
- pr_warn("%s: rde->offset 0x%llx ctx->pos 0x%llx\n",
- __func__, rde->offset, ctx->pos);
+ pr_warn_client(cl,
+ "%p %llx.%llx rde->offset 0x%llx ctx->pos 0x%llx\n",
+ inode, ceph_vinop(inode), rde->offset, ctx->pos);
+ ceph_mdsc_put_request(dfi->last_readdir);
+ dfi->last_readdir = NULL;
return -EIO;
}
- if (WARN_ON_ONCE(!rde->inode.in))
+ if (WARN_ON_ONCE(!rde->inode.in)) {
+ ceph_mdsc_put_request(dfi->last_readdir);
+ dfi->last_readdir = NULL;
return -EIO;
+ }
ctx->pos = rde->offset;
- dout("readdir (%d/%d) -> %llx '%.*s' %p\n",
- i, rinfo->dir_nr, ctx->pos,
- rde->name_len, rde->name, &rde->inode.in);
+ doutc(cl, "%p %llx.%llx (%d/%d) -> %llx '%.*s' %p\n", inode,
+ ceph_vinop(inode), i, rinfo->dir_nr, ctx->pos,
+ rde->name_len, rde->name, &rde->inode.in);
if (!dir_emit(ctx, rde->name, rde->name_len,
ceph_present_ino(inode->i_sb, le64_to_cpu(rde->inode.in->ino)),
@@ -552,7 +571,7 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
* doesn't have enough memory, etc. So for next readdir
* it will continue.
*/
- dout("filldir stopping us...\n");
+ doutc(cl, "filldir stopping us...\n");
return 0;
}
@@ -583,7 +602,8 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
kfree(dfi->last_name);
dfi->last_name = NULL;
}
- dout("readdir next frag is %x\n", frag);
+ doutc(cl, "%p %llx.%llx next frag is %x\n", inode,
+ ceph_vinop(inode), frag);
goto more;
}
dfi->file_info.flags |= CEPH_F_ATEND;
@@ -598,20 +618,23 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
spin_lock(&ci->i_ceph_lock);
if (dfi->dir_ordered_count ==
atomic64_read(&ci->i_ordered_count)) {
- dout(" marking %p complete and ordered\n", inode);
+ doutc(cl, " marking %p %llx.%llx complete and ordered\n",
+ inode, ceph_vinop(inode));
/* use i_size to track number of entries in
* readdir cache */
BUG_ON(dfi->readdir_cache_idx < 0);
i_size_write(inode, dfi->readdir_cache_idx *
sizeof(struct dentry*));
} else {
- dout(" marking %p complete\n", inode);
+ doutc(cl, " marking %llx.%llx complete\n",
+ ceph_vinop(inode));
}
__ceph_dir_set_complete(ci, dfi->dir_release_count,
dfi->dir_ordered_count);
spin_unlock(&ci->i_ceph_lock);
}
- dout("readdir %p file %p done.\n", inode, file);
+ doutc(cl, "%p %llx.%llx file %p done.\n", inode, ceph_vinop(inode),
+ file);
return 0;
}
@@ -657,6 +680,7 @@ static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int whence)
{
struct ceph_dir_file_info *dfi = file->private_data;
struct inode *inode = file->f_mapping->host;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
loff_t retval;
inode_lock(inode);
@@ -676,7 +700,8 @@ static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int whence)
if (offset >= 0) {
if (need_reset_readdir(dfi, offset)) {
- dout("dir_llseek dropping %p content\n", file);
+ doutc(cl, "%p %llx.%llx dropping %p content\n",
+ inode, ceph_vinop(inode), file);
reset_readdir(dfi);
} else if (is_hash_order(offset) && offset > file->f_pos) {
/* for hash offset, we don't know if a forward seek
@@ -705,6 +730,7 @@ struct dentry *ceph_handle_snapdir(struct ceph_mds_request *req,
{
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dentry->d_sb);
struct inode *parent = d_inode(dentry->d_parent); /* we hold i_rwsem */
+ struct ceph_client *cl = ceph_inode_to_client(parent);
/* .snap dir? */
if (ceph_snap(parent) == CEPH_NOSNAP &&
@@ -713,8 +739,9 @@ struct dentry *ceph_handle_snapdir(struct ceph_mds_request *req,
struct inode *inode = ceph_get_snapdir(parent);
res = d_splice_alias(inode, dentry);
- dout("ENOENT on snapdir %p '%pd', linking to snapdir %p. Spliced dentry %p\n",
- dentry, dentry, inode, res);
+ doutc(cl, "ENOENT on snapdir %p '%pd', linking to "
+ "snapdir %p %llx.%llx. Spliced dentry %p\n",
+ dentry, dentry, inode, ceph_vinop(inode), res);
if (res)
dentry = res;
}
@@ -735,12 +762,15 @@ struct dentry *ceph_handle_snapdir(struct ceph_mds_request *req,
struct dentry *ceph_finish_lookup(struct ceph_mds_request *req,
struct dentry *dentry, int err)
{
+ struct ceph_client *cl = req->r_mdsc->fsc->client;
+
if (err == -ENOENT) {
/* no trace? */
err = 0;
if (!req->r_reply_info.head->is_dentry) {
- dout("ENOENT and no trace, dentry %p inode %p\n",
- dentry, d_inode(dentry));
+ doutc(cl,
+ "ENOENT and no trace, dentry %p inode %llx.%llx\n",
+ dentry, ceph_vinop(d_inode(dentry)));
if (d_really_is_positive(dentry)) {
d_drop(dentry);
err = -ENOENT;
@@ -774,13 +804,14 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
{
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dir->i_sb);
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
+ struct ceph_client *cl = fsc->client;
struct ceph_mds_request *req;
int op;
int mask;
int err;
- dout("lookup %p dentry %p '%pd'\n",
- dir, dentry, dentry);
+ doutc(cl, "%p %llx.%llx/'%pd' dentry %p\n", dir, ceph_vinop(dir),
+ dentry, dentry);
if (dentry->d_name.len > NAME_MAX)
return ERR_PTR(-ENAMETOOLONG);
@@ -803,7 +834,8 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
struct ceph_dentry_info *di = ceph_dentry(dentry);
spin_lock(&ci->i_ceph_lock);
- dout(" dir %p flags are 0x%lx\n", dir, ci->i_ceph_flags);
+ doutc(cl, " dir %llx.%llx flags are 0x%lx\n",
+ ceph_vinop(dir), ci->i_ceph_flags);
if (strncmp(dentry->d_name.name,
fsc->mount_options->snapdir_name,
dentry->d_name.len) &&
@@ -813,7 +845,8 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
__ceph_caps_issued_mask_metric(ci, CEPH_CAP_FILE_SHARED, 1)) {
__ceph_touch_fmode(ci, mdsc, CEPH_FILE_MODE_RD);
spin_unlock(&ci->i_ceph_lock);
- dout(" dir %p complete, -ENOENT\n", dir);
+ doutc(cl, " dir %llx.%llx complete, -ENOENT\n",
+ ceph_vinop(dir));
if (d_unhashed(dentry))
d_add(dentry, NULL);
di->lease_shared_gen = atomic_read(&ci->i_shared_gen);
@@ -852,7 +885,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
}
dentry = ceph_finish_lookup(req, dentry, err);
ceph_mdsc_put_request(req); /* will dput(dentry) */
- dout("lookup result=%p\n", dentry);
+ doutc(cl, "result=%p\n", dentry);
return dentry;
}
@@ -887,6 +920,7 @@ static int ceph_mknod(struct mnt_idmap *idmap, struct inode *dir,
struct dentry *dentry, umode_t mode, dev_t rdev)
{
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mds_request *req;
struct ceph_acl_sec_ctx as_ctx = {};
int err;
@@ -903,8 +937,8 @@ static int ceph_mknod(struct mnt_idmap *idmap, struct inode *dir,
goto out;
}
- dout("mknod in dir %p dentry %p mode 0%ho rdev %d\n",
- dir, dentry, mode, rdev);
+ doutc(cl, "%p %llx.%llx/'%pd' dentry %p mode 0%ho rdev %d\n",
+ dir, ceph_vinop(dir), dentry, dentry, mode, rdev);
req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_MKNOD, USE_AUTH_MDS);
if (IS_ERR(req)) {
err = PTR_ERR(req);
@@ -995,6 +1029,7 @@ static int ceph_symlink(struct mnt_idmap *idmap, struct inode *dir,
struct dentry *dentry, const char *dest)
{
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mds_request *req;
struct ceph_acl_sec_ctx as_ctx = {};
umode_t mode = S_IFLNK | 0777;
@@ -1012,7 +1047,8 @@ static int ceph_symlink(struct mnt_idmap *idmap, struct inode *dir,
goto out;
}
- dout("symlink in dir %p dentry %p to '%s'\n", dir, dentry, dest);
+ doutc(cl, "%p %llx.%llx/'%pd' to '%s'\n", dir, ceph_vinop(dir), dentry,
+ dest);
req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SYMLINK, USE_AUTH_MDS);
if (IS_ERR(req)) {
err = PTR_ERR(req);
@@ -1066,6 +1102,7 @@ static int ceph_mkdir(struct mnt_idmap *idmap, struct inode *dir,
struct dentry *dentry, umode_t mode)
{
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mds_request *req;
struct ceph_acl_sec_ctx as_ctx = {};
int err;
@@ -1078,10 +1115,11 @@ static int ceph_mkdir(struct mnt_idmap *idmap, struct inode *dir,
if (ceph_snap(dir) == CEPH_SNAPDIR) {
/* mkdir .snap/foo is a MKSNAP */
op = CEPH_MDS_OP_MKSNAP;
- dout("mksnap dir %p snap '%pd' dn %p\n", dir,
- dentry, dentry);
+ doutc(cl, "mksnap %llx.%llx/'%pd' dentry %p\n",
+ ceph_vinop(dir), dentry, dentry);
} else if (ceph_snap(dir) == CEPH_NOSNAP) {
- dout("mkdir dir %p dn %p mode 0%ho\n", dir, dentry, mode);
+ doutc(cl, "mkdir %llx.%llx/'%pd' dentry %p mode 0%ho\n",
+ ceph_vinop(dir), dentry, dentry, mode);
op = CEPH_MDS_OP_MKDIR;
} else {
err = -EROFS;
@@ -1146,6 +1184,7 @@ static int ceph_link(struct dentry *old_dentry, struct inode *dir,
struct dentry *dentry)
{
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mds_request *req;
int err;
@@ -1163,8 +1202,8 @@ static int ceph_link(struct dentry *old_dentry, struct inode *dir,
if (err)
return err;
- dout("link in dir %p %llx.%llx old_dentry %p:'%pd' dentry %p:'%pd'\n",
- dir, ceph_vinop(dir), old_dentry, old_dentry, dentry, dentry);
+ doutc(cl, "%p %llx.%llx/'%pd' to '%pd'\n", dir, ceph_vinop(dir),
+ old_dentry, dentry);
req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LINK, USE_AUTH_MDS);
if (IS_ERR(req)) {
d_drop(dentry);
@@ -1202,13 +1241,15 @@ static void ceph_async_unlink_cb(struct ceph_mds_client *mdsc,
{
struct dentry *dentry = req->r_dentry;
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dentry->d_sb);
+ struct ceph_client *cl = fsc->client;
struct ceph_dentry_info *di = ceph_dentry(dentry);
int result = req->r_err ? req->r_err :
le32_to_cpu(req->r_reply_info.head->result);
if (!test_bit(CEPH_DENTRY_ASYNC_UNLINK_BIT, &di->flags))
- pr_warn("%s dentry %p:%pd async unlink bit is not set\n",
- __func__, dentry, dentry);
+ pr_warn_client(cl,
+ "dentry %p:%pd async unlink bit is not set\n",
+ dentry, dentry);
spin_lock(&fsc->async_unlink_conflict_lock);
hash_del_rcu(&di->hnode);
@@ -1241,8 +1282,8 @@ static void ceph_async_unlink_cb(struct ceph_mds_client *mdsc,
/* mark inode itself for an error (since metadata is bogus) */
mapping_set_error(req->r_old_inode->i_mapping, result);
- pr_warn("async unlink failure path=(%llx)%s result=%d!\n",
- base, IS_ERR(path) ? "<<bad>>" : path, result);
+ pr_warn_client(cl, "failure path=(%llx)%s result=%d!\n",
+ base, IS_ERR(path) ? "<<bad>>" : path, result);
ceph_mdsc_free_path(path, pathlen);
}
out:
@@ -1292,6 +1333,7 @@ static int get_caps_for_async_unlink(struct inode *dir, struct dentry *dentry)
static int ceph_unlink(struct inode *dir, struct dentry *dentry)
{
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dir->i_sb);
+ struct ceph_client *cl = fsc->client;
struct ceph_mds_client *mdsc = fsc->mdsc;
struct inode *inode = d_inode(dentry);
struct ceph_inode_info *ci = ceph_inode(inode);
@@ -1302,11 +1344,12 @@ static int ceph_unlink(struct inode *dir, struct dentry *dentry)
if (ceph_snap(dir) == CEPH_SNAPDIR) {
/* rmdir .snap/foo is RMSNAP */
- dout("rmsnap dir %p '%pd' dn %p\n", dir, dentry, dentry);
+ doutc(cl, "rmsnap %llx.%llx/'%pd' dn\n", ceph_vinop(dir),
+ dentry);
op = CEPH_MDS_OP_RMSNAP;
} else if (ceph_snap(dir) == CEPH_NOSNAP) {
- dout("unlink/rmdir dir %p dn %p inode %p\n",
- dir, dentry, inode);
+ doutc(cl, "unlink/rmdir %llx.%llx/'%pd' inode %llx.%llx\n",
+ ceph_vinop(dir), dentry, ceph_vinop(inode));
op = d_is_dir(dentry) ?
CEPH_MDS_OP_RMDIR : CEPH_MDS_OP_UNLINK;
} else
@@ -1329,9 +1372,9 @@ static int ceph_unlink(struct inode *dir, struct dentry *dentry)
(req->r_dir_caps = get_caps_for_async_unlink(dir, dentry))) {
struct ceph_dentry_info *di = ceph_dentry(dentry);
- dout("async unlink on %llu/%.*s caps=%s", ceph_ino(dir),
- dentry->d_name.len, dentry->d_name.name,
- ceph_cap_string(req->r_dir_caps));
+ doutc(cl, "async unlink on %llx.%llx/'%pd' caps=%s",
+ ceph_vinop(dir), dentry,
+ ceph_cap_string(req->r_dir_caps));
set_bit(CEPH_MDS_R_ASYNC, &req->r_req_flags);
req->r_callback = ceph_async_unlink_cb;
req->r_old_inode = d_inode(dentry);
@@ -1398,6 +1441,7 @@ static int ceph_rename(struct mnt_idmap *idmap, struct inode *old_dir,
struct dentry *new_dentry, unsigned int flags)
{
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(old_dir->i_sb);
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mds_request *req;
int op = CEPH_MDS_OP_RENAME;
int err;
@@ -1427,8 +1471,9 @@ static int ceph_rename(struct mnt_idmap *idmap, struct inode *old_dir,
if (err)
return err;
- dout("rename dir %p dentry %p to dir %p dentry %p\n",
- old_dir, old_dentry, new_dir, new_dentry);
+ doutc(cl, "%llx.%llx/'%pd' to %llx.%llx/'%pd'\n",
+ ceph_vinop(old_dir), old_dentry, ceph_vinop(new_dir),
+ new_dentry);
req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS);
if (IS_ERR(req))
return PTR_ERR(req);
@@ -1473,9 +1518,10 @@ static int ceph_rename(struct mnt_idmap *idmap, struct inode *old_dir,
void __ceph_dentry_lease_touch(struct ceph_dentry_info *di)
{
struct dentry *dn = di->dentry;
- struct ceph_mds_client *mdsc;
+ struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(dn->d_sb)->mdsc;
+ struct ceph_client *cl = mdsc->fsc->client;
- dout("dentry_lease_touch %p %p '%pd'\n", di, dn, dn);
+ doutc(cl, "%p %p '%pd'\n", di, dn, dn);
di->flags |= CEPH_DENTRY_LEASE_LIST;
if (di->flags & CEPH_DENTRY_SHRINK_LIST) {
@@ -1483,7 +1529,6 @@ void __ceph_dentry_lease_touch(struct ceph_dentry_info *di)
return;
}
- mdsc = ceph_sb_to_fs_client(dn->d_sb)->mdsc;
spin_lock(&mdsc->dentry_list_lock);
list_move_tail(&di->lease_list, &mdsc->dentry_leases);
spin_unlock(&mdsc->dentry_list_lock);
@@ -1507,10 +1552,10 @@ static void __dentry_dir_lease_touch(struct ceph_mds_client* mdsc,
void __ceph_dentry_dir_lease_touch(struct ceph_dentry_info *di)
{
struct dentry *dn = di->dentry;
- struct ceph_mds_client *mdsc;
+ struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(dn->d_sb)->mdsc;
+ struct ceph_client *cl = mdsc->fsc->client;
- dout("dentry_dir_lease_touch %p %p '%pd' (offset 0x%llx)\n",
- di, dn, dn, di->offset);
+ doutc(cl, "%p %p '%pd' (offset 0x%llx)\n", di, dn, dn, di->offset);
if (!list_empty(&di->lease_list)) {
if (di->flags & CEPH_DENTRY_LEASE_LIST) {
@@ -1530,7 +1575,6 @@ void __ceph_dentry_dir_lease_touch(struct ceph_dentry_info *di)
return;
}
- mdsc = ceph_sb_to_fs_client(dn->d_sb)->mdsc;
spin_lock(&mdsc->dentry_list_lock);
__dentry_dir_lease_touch(mdsc, di),
spin_unlock(&mdsc->dentry_list_lock);
@@ -1771,6 +1815,8 @@ static int dentry_lease_is_valid(struct dentry *dentry, unsigned int flags)
{
struct ceph_dentry_info *di;
struct ceph_mds_session *session = NULL;
+ struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(dentry->d_sb)->mdsc;
+ struct ceph_client *cl = mdsc->fsc->client;
u32 seq = 0;
int valid = 0;
@@ -1803,7 +1849,7 @@ static int dentry_lease_is_valid(struct dentry *dentry, unsigned int flags)
CEPH_MDS_LEASE_RENEW, seq);
ceph_put_mds_session(session);
}
- dout("dentry_lease_is_valid - dentry %p = %d\n", dentry, valid);
+ doutc(cl, "dentry %p = %d\n", dentry, valid);
return valid;
}
@@ -1846,6 +1892,7 @@ static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry,
struct ceph_mds_client *mdsc)
{
struct ceph_inode_info *ci = ceph_inode(dir);
+ struct ceph_client *cl = mdsc->fsc->client;
int valid;
int shared_gen;
@@ -1867,8 +1914,9 @@ static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry,
valid = 0;
spin_unlock(&dentry->d_lock);
}
- dout("dir_lease_is_valid dir %p v%u dentry %p = %d\n",
- dir, (unsigned)atomic_read(&ci->i_shared_gen), dentry, valid);
+ doutc(cl, "dir %p %llx.%llx v%u dentry %p '%pd' = %d\n", dir,
+ ceph_vinop(dir), (unsigned)atomic_read(&ci->i_shared_gen),
+ dentry, dentry, valid);
return valid;
}
@@ -1877,10 +1925,11 @@ static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry,
*/
static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
{
+ struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(dentry->d_sb)->mdsc;
+ struct ceph_client *cl = mdsc->fsc->client;
int valid = 0;
struct dentry *parent;
struct inode *dir, *inode;
- struct ceph_mds_client *mdsc;
valid = fscrypt_d_revalidate(dentry, flags);
if (valid <= 0)
@@ -1898,16 +1947,16 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
inode = d_inode(dentry);
}
- dout("d_revalidate %p '%pd' inode %p offset 0x%llx nokey %d\n", dentry,
- dentry, inode, ceph_dentry(dentry)->offset,
- !!(dentry->d_flags & DCACHE_NOKEY_NAME));
+ doutc(cl, "%p '%pd' inode %p offset 0x%llx nokey %d\n",
+ dentry, dentry, inode, ceph_dentry(dentry)->offset,
+ !!(dentry->d_flags & DCACHE_NOKEY_NAME));
mdsc = ceph_sb_to_fs_client(dir->i_sb)->mdsc;
/* always trust cached snapped dentries, snapdir dentry */
if (ceph_snap(dir) != CEPH_NOSNAP) {
- dout("d_revalidate %p '%pd' inode %p is SNAPPED\n", dentry,
- dentry, inode);
+ doutc(cl, "%p '%pd' inode %p is SNAPPED\n", dentry,
+ dentry, inode);
valid = 1;
} else if (inode && ceph_snap(inode) == CEPH_SNAPDIR) {
valid = 1;
@@ -1962,14 +2011,14 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
break;
}
ceph_mdsc_put_request(req);
- dout("d_revalidate %p lookup result=%d\n",
- dentry, err);
+ doutc(cl, "%p '%pd', lookup result=%d\n", dentry,
+ dentry, err);
}
} else {
percpu_counter_inc(&mdsc->metric.d_lease_hit);
}
- dout("d_revalidate %p %s\n", dentry, valid ? "valid" : "invalid");
+ doutc(cl, "%p '%pd' %s\n", dentry, dentry, valid ? "valid" : "invalid");
if (!valid)
ceph_dir_clear_complete(dir);
@@ -2011,7 +2060,7 @@ static void ceph_d_release(struct dentry *dentry)
struct ceph_dentry_info *di = ceph_dentry(dentry);
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dentry->d_sb);
- dout("d_release %p\n", dentry);
+ doutc(fsc->client, "dentry %p '%pd'\n", dentry, dentry);
atomic64_dec(&fsc->mdsc->metric.total_dentries);
@@ -2032,10 +2081,12 @@ static void ceph_d_release(struct dentry *dentry)
*/
static void ceph_d_prune(struct dentry *dentry)
{
+ struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dentry->d_sb);
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_inode_info *dir_ci;
struct ceph_dentry_info *di;
- dout("ceph_d_prune %pd %p\n", dentry, dentry);
+ doutc(cl, "dentry %p '%pd'\n", dentry, dentry);
/* do we have a valid parent? */
if (IS_ROOT(dentry))
diff --git a/fs/ceph/export.c b/fs/ceph/export.c
index 52c4daf2447d..726af69d4d62 100644
--- a/fs/ceph/export.c
+++ b/fs/ceph/export.c
@@ -36,6 +36,7 @@ struct ceph_nfs_snapfh {
static int ceph_encode_snapfh(struct inode *inode, u32 *rawfh, int *max_len,
struct inode *parent_inode)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
static const int snap_handle_length =
sizeof(struct ceph_nfs_snapfh) >> 2;
struct ceph_nfs_snapfh *sfh = (void *)rawfh;
@@ -79,13 +80,14 @@ static int ceph_encode_snapfh(struct inode *inode, u32 *rawfh, int *max_len,
*max_len = snap_handle_length;
ret = FILEID_BTRFS_WITH_PARENT;
out:
- dout("encode_snapfh %llx.%llx ret=%d\n", ceph_vinop(inode), ret);
+ doutc(cl, "%p %llx.%llx ret=%d\n", inode, ceph_vinop(inode), ret);
return ret;
}
static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len,
struct inode *parent_inode)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
static const int handle_length =
sizeof(struct ceph_nfs_fh) >> 2;
static const int connected_handle_length =
@@ -105,15 +107,15 @@ static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len,
if (parent_inode) {
struct ceph_nfs_confh *cfh = (void *)rawfh;
- dout("encode_fh %llx with parent %llx\n",
- ceph_ino(inode), ceph_ino(parent_inode));
+ doutc(cl, "%p %llx.%llx with parent %p %llx.%llx\n", inode,
+ ceph_vinop(inode), parent_inode, ceph_vinop(parent_inode));
cfh->ino = ceph_ino(inode);
cfh->parent_ino = ceph_ino(parent_inode);
*max_len = connected_handle_length;
type = FILEID_INO32_GEN_PARENT;
} else {
struct ceph_nfs_fh *fh = (void *)rawfh;
- dout("encode_fh %llx\n", ceph_ino(inode));
+ doutc(cl, "%p %llx.%llx\n", inode, ceph_vinop(inode));
fh->ino = ceph_ino(inode);
*max_len = handle_length;
type = FILEID_INO32_GEN;
@@ -206,6 +208,7 @@ static struct dentry *__snapfh_to_dentry(struct super_block *sb,
bool want_parent)
{
struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(sb)->mdsc;
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mds_request *req;
struct inode *inode;
struct ceph_vino vino;
@@ -278,11 +281,10 @@ static struct dentry *__snapfh_to_dentry(struct super_block *sb,
ceph_mdsc_put_request(req);
if (want_parent) {
- dout("snapfh_to_parent %llx.%llx\n err=%d\n",
- vino.ino, vino.snap, err);
+ doutc(cl, "%llx.%llx\n err=%d\n", vino.ino, vino.snap, err);
} else {
- dout("snapfh_to_dentry %llx.%llx parent %llx hash %x err=%d",
- vino.ino, vino.snap, sfh->parent_ino, sfh->hash, err);
+ doutc(cl, "%llx.%llx parent %llx hash %x err=%d", vino.ino,
+ vino.snap, sfh->parent_ino, sfh->hash, err);
}
if (IS_ERR(inode))
return ERR_CAST(inode);
@@ -297,6 +299,7 @@ static struct dentry *ceph_fh_to_dentry(struct super_block *sb,
struct fid *fid,
int fh_len, int fh_type)
{
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb);
struct ceph_nfs_fh *fh = (void *)fid->raw;
if (fh_type == FILEID_BTRFS_WITH_PARENT) {
@@ -310,7 +313,7 @@ static struct dentry *ceph_fh_to_dentry(struct super_block *sb,
if (fh_len < sizeof(*fh) / 4)
return NULL;
- dout("fh_to_dentry %llx\n", fh->ino);
+ doutc(fsc->client, "%llx\n", fh->ino);
return __fh_to_dentry(sb, fh->ino);
}
@@ -363,6 +366,7 @@ static struct dentry *__get_parent(struct super_block *sb,
static struct dentry *ceph_get_parent(struct dentry *child)
{
struct inode *inode = d_inode(child);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct dentry *dn;
if (ceph_snap(inode) != CEPH_NOSNAP) {
@@ -402,8 +406,8 @@ static struct dentry *ceph_get_parent(struct dentry *child)
dn = __get_parent(child->d_sb, child, 0);
}
out:
- dout("get_parent %p ino %llx.%llx err=%ld\n",
- child, ceph_vinop(inode), (long)PTR_ERR_OR_ZERO(dn));
+ doutc(cl, "child %p %p %llx.%llx err=%ld\n", child, inode,
+ ceph_vinop(inode), (long)PTR_ERR_OR_ZERO(dn));
return dn;
}
@@ -414,6 +418,7 @@ static struct dentry *ceph_fh_to_parent(struct super_block *sb,
struct fid *fid,
int fh_len, int fh_type)
{
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb);
struct ceph_nfs_confh *cfh = (void *)fid->raw;
struct dentry *dentry;
@@ -427,7 +432,7 @@ static struct dentry *ceph_fh_to_parent(struct super_block *sb,
if (fh_len < sizeof(*cfh) / 4)
return NULL;
- dout("fh_to_parent %llx\n", cfh->parent_ino);
+ doutc(fsc->client, "%llx\n", cfh->parent_ino);
dentry = __get_parent(sb, NULL, cfh->ino);
if (unlikely(dentry == ERR_PTR(-ENOENT)))
dentry = __fh_to_dentry(sb, cfh->parent_ino);
@@ -526,8 +531,8 @@ static int __get_snap_name(struct dentry *parent, char *name,
if (req)
ceph_mdsc_put_request(req);
kfree(last_name);
- dout("get_snap_name %p ino %llx.%llx err=%d\n",
- child, ceph_vinop(inode), err);
+ doutc(fsc->client, "child dentry %p %p %llx.%llx err=%d\n", child,
+ inode, ceph_vinop(inode), err);
return err;
}
@@ -588,9 +593,9 @@ static int ceph_get_name(struct dentry *parent, char *name,
ceph_fname_free_buffer(dir, &oname);
}
out:
- dout("get_name %p ino %llx.%llx err %d %s%s\n",
- child, ceph_vinop(inode), err,
- err ? "" : "name ", err ? "" : name);
+ doutc(mdsc->fsc->client, "child dentry %p %p %llx.%llx err %d %s%s\n",
+ child, inode, ceph_vinop(inode), err, err ? "" : "name ",
+ err ? "" : name);
ceph_mdsc_put_request(req);
return err;
}
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 0757eb7611da..bd74e8ffe6af 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -19,8 +19,9 @@
#include "io.h"
#include "metric.h"
-static __le32 ceph_flags_sys2wire(u32 flags)
+static __le32 ceph_flags_sys2wire(struct ceph_mds_client *mdsc, u32 flags)
{
+ struct ceph_client *cl = mdsc->fsc->client;
u32 wire_flags = 0;
switch (flags & O_ACCMODE) {
@@ -48,7 +49,7 @@ static __le32 ceph_flags_sys2wire(u32 flags)
#undef ceph_sys2wire
if (flags)
- dout("unused open flags: %x\n", flags);
+ doutc(cl, "unused open flags: %x\n", flags);
return cpu_to_le32(wire_flags);
}
@@ -189,7 +190,7 @@ prepare_open_request(struct super_block *sb, int flags, int create_mode)
if (IS_ERR(req))
goto out;
req->r_fmode = ceph_flags_to_mode(flags);
- req->r_args.open.flags = ceph_flags_sys2wire(flags);
+ req->r_args.open.flags = ceph_flags_sys2wire(mdsc, flags);
req->r_args.open.mode = cpu_to_le32(create_mode);
out:
return req;
@@ -201,11 +202,12 @@ static int ceph_init_file_info(struct inode *inode, struct file *file,
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_mount_options *opt =
ceph_inode_to_fs_client(&ci->netfs.inode)->mount_options;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_file_info *fi;
int ret;
- dout("%s %p %p 0%o (%s)\n", __func__, inode, file,
- inode->i_mode, isdir ? "dir" : "regular");
+ doutc(cl, "%p %llx.%llx %p 0%o (%s)\n", inode, ceph_vinop(inode),
+ file, inode->i_mode, isdir ? "dir" : "regular");
BUG_ON(inode->i_fop->release != ceph_release);
if (isdir) {
@@ -259,6 +261,7 @@ static int ceph_init_file_info(struct inode *inode, struct file *file,
*/
static int ceph_init_file(struct inode *inode, struct file *file, int fmode)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
int ret = 0;
switch (inode->i_mode & S_IFMT) {
@@ -271,13 +274,13 @@ static int ceph_init_file(struct inode *inode, struct file *file, int fmode)
break;
case S_IFLNK:
- dout("init_file %p %p 0%o (symlink)\n", inode, file,
- inode->i_mode);
+ doutc(cl, "%p %llx.%llx %p 0%o (symlink)\n", inode,
+ ceph_vinop(inode), file, inode->i_mode);
break;
default:
- dout("init_file %p %p 0%o (special)\n", inode, file,
- inode->i_mode);
+ doutc(cl, "%p %llx.%llx %p 0%o (special)\n", inode,
+ ceph_vinop(inode), file, inode->i_mode);
/*
* we need to drop the open ref now, since we don't
* have .release set to ceph_release.
@@ -296,6 +299,7 @@ static int ceph_init_file(struct inode *inode, struct file *file, int fmode)
int ceph_renew_caps(struct inode *inode, int fmode)
{
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_mds_request *req;
int err, flags, wanted;
@@ -307,8 +311,9 @@ int ceph_renew_caps(struct inode *inode, int fmode)
(!(wanted & CEPH_CAP_ANY_WR) || ci->i_auth_cap)) {
int issued = __ceph_caps_issued(ci, NULL);
spin_unlock(&ci->i_ceph_lock);
- dout("renew caps %p want %s issued %s updating mds_wanted\n",
- inode, ceph_cap_string(wanted), ceph_cap_string(issued));
+ doutc(cl, "%p %llx.%llx want %s issued %s updating mds_wanted\n",
+ inode, ceph_vinop(inode), ceph_cap_string(wanted),
+ ceph_cap_string(issued));
ceph_check_caps(ci, 0);
return 0;
}
@@ -339,7 +344,8 @@ int ceph_renew_caps(struct inode *inode, int fmode)
err = ceph_mdsc_do_request(mdsc, NULL, req);
ceph_mdsc_put_request(req);
out:
- dout("renew caps %p open result=%d\n", inode, err);
+ doutc(cl, "%p %llx.%llx open result=%d\n", inode, ceph_vinop(inode),
+ err);
return err < 0 ? err : 0;
}
@@ -353,6 +359,7 @@ int ceph_open(struct inode *inode, struct file *file)
{
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(inode->i_sb);
+ struct ceph_client *cl = fsc->client;
struct ceph_mds_client *mdsc = fsc->mdsc;
struct ceph_mds_request *req;
struct ceph_file_info *fi = file->private_data;
@@ -360,7 +367,7 @@ int ceph_open(struct inode *inode, struct file *file)
int flags, fmode, wanted;
if (fi) {
- dout("open file %p is already opened\n", file);
+ doutc(cl, "file %p is already opened\n", file);
return 0;
}
@@ -374,8 +381,8 @@ int ceph_open(struct inode *inode, struct file *file)
return err;
}
- dout("open inode %p ino %llx.%llx file %p flags %d (%d)\n", inode,
- ceph_vinop(inode), file, flags, file->f_flags);
+ doutc(cl, "%p %llx.%llx file %p flags %d (%d)\n", inode,
+ ceph_vinop(inode), file, flags, file->f_flags);
fmode = ceph_flags_to_mode(flags);
wanted = ceph_caps_for_mode(fmode);
@@ -399,9 +406,9 @@ int ceph_open(struct inode *inode, struct file *file)
int mds_wanted = __ceph_caps_mds_wanted(ci, true);
int issued = __ceph_caps_issued(ci, NULL);
- dout("open %p fmode %d want %s issued %s using existing\n",
- inode, fmode, ceph_cap_string(wanted),
- ceph_cap_string(issued));
+ doutc(cl, "open %p fmode %d want %s issued %s using existing\n",
+ inode, fmode, ceph_cap_string(wanted),
+ ceph_cap_string(issued));
__ceph_touch_fmode(ci, mdsc, fmode);
spin_unlock(&ci->i_ceph_lock);
@@ -421,7 +428,7 @@ int ceph_open(struct inode *inode, struct file *file)
spin_unlock(&ci->i_ceph_lock);
- dout("open fmode %d wants %s\n", fmode, ceph_cap_string(wanted));
+ doutc(cl, "open fmode %d wants %s\n", fmode, ceph_cap_string(wanted));
req = prepare_open_request(inode->i_sb, flags, 0);
if (IS_ERR(req)) {
err = PTR_ERR(req);
@@ -435,7 +442,7 @@ int ceph_open(struct inode *inode, struct file *file)
if (!err)
err = ceph_init_file(inode, file, req->r_fmode);
ceph_mdsc_put_request(req);
- dout("open result=%d on %llx.%llx\n", err, ceph_vinop(inode));
+ doutc(cl, "open result=%d on %llx.%llx\n", err, ceph_vinop(inode));
out:
return err;
}
@@ -515,6 +522,7 @@ static int try_prep_async_create(struct inode *dir, struct dentry *dentry,
static void restore_deleg_ino(struct inode *dir, u64 ino)
{
+ struct ceph_client *cl = ceph_inode_to_client(dir);
struct ceph_inode_info *ci = ceph_inode(dir);
struct ceph_mds_session *s = NULL;
@@ -525,7 +533,8 @@ static void restore_deleg_ino(struct inode *dir, u64 ino)
if (s) {
int err = ceph_restore_deleg_ino(s, ino);
if (err)
- pr_warn("ceph: unable to restore delegated ino 0x%llx to session: %d\n",
+ pr_warn_client(cl,
+ "unable to restore delegated ino 0x%llx to session: %d\n",
ino, err);
ceph_put_mds_session(s);
}
@@ -556,6 +565,7 @@ static void wake_async_create_waiters(struct inode *inode,
static void ceph_async_create_cb(struct ceph_mds_client *mdsc,
struct ceph_mds_request *req)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct dentry *dentry = req->r_dentry;
struct inode *dinode = d_inode(dentry);
struct inode *tinode = req->r_target_inode;
@@ -576,7 +586,8 @@ static void ceph_async_create_cb(struct ceph_mds_client *mdsc,
char *path = ceph_mdsc_build_path(mdsc, req->r_dentry, &pathlen,
&base, 0);
- pr_warn("async create failure path=(%llx)%s result=%d!\n",
+ pr_warn_client(cl,
+ "async create failure path=(%llx)%s result=%d!\n",
base, IS_ERR(path) ? "<<bad>>" : path, result);
ceph_mdsc_free_path(path, pathlen);
@@ -595,14 +606,15 @@ static void ceph_async_create_cb(struct ceph_mds_client *mdsc,
u64 ino = ceph_vino(tinode).ino;
if (req->r_deleg_ino != ino)
- pr_warn("%s: inode number mismatch! err=%d deleg_ino=0x%llx target=0x%llx\n",
- __func__, req->r_err, req->r_deleg_ino, ino);
+ pr_warn_client(cl,
+ "inode number mismatch! err=%d deleg_ino=0x%llx target=0x%llx\n",
+ req->r_err, req->r_deleg_ino, ino);
mapping_set_error(tinode->i_mapping, result);
wake_async_create_waiters(tinode, req->r_session);
} else if (!result) {
- pr_warn("%s: no req->r_target_inode for 0x%llx\n", __func__,
- req->r_deleg_ino);
+ pr_warn_client(cl, "no req->r_target_inode for 0x%llx\n",
+ req->r_deleg_ino);
}
out:
ceph_mdsc_release_dir_caps(req);
@@ -624,6 +636,7 @@ static int ceph_finish_async_create(struct inode *dir, struct inode *inode,
struct timespec64 now;
struct ceph_string *pool_ns;
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_vino vino = { .ino = req->r_deleg_ino,
.snap = CEPH_NOSNAP };
@@ -682,7 +695,7 @@ static int ceph_finish_async_create(struct inode *dir, struct inode *inode,
req->r_fmode, NULL);
up_read(&mdsc->snap_rwsem);
if (ret) {
- dout("%s failed to fill inode: %d\n", __func__, ret);
+ doutc(cl, "failed to fill inode: %d\n", ret);
ceph_dir_clear_complete(dir);
if (!d_unhashed(dentry))
d_drop(dentry);
@@ -690,8 +703,8 @@ static int ceph_finish_async_create(struct inode *dir, struct inode *inode,
} else {
struct dentry *dn;
- dout("%s d_adding new inode 0x%llx to 0x%llx/%s\n", __func__,
- vino.ino, ceph_ino(dir), dentry->d_name.name);
+ doutc(cl, "d_adding new inode 0x%llx to 0x%llx/%s\n",
+ vino.ino, ceph_ino(dir), dentry->d_name.name);
ceph_dir_clear_ordered(dir);
ceph_init_inode_acls(inode, as_ctx);
if (inode->i_state & I_NEW) {
@@ -729,6 +742,7 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
struct file *file, unsigned flags, umode_t mode)
{
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dir->i_sb);
+ struct ceph_client *cl = fsc->client;
struct ceph_mds_client *mdsc = fsc->mdsc;
struct ceph_mds_request *req;
struct inode *new_inode = NULL;
@@ -738,9 +752,9 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
int mask;
int err;
- dout("atomic_open %p dentry %p '%pd' %s flags %d mode 0%o\n",
- dir, dentry, dentry,
- d_unhashed(dentry) ? "unhashed" : "hashed", flags, mode);
+ doutc(cl, "%p %llx.%llx dentry %p '%pd' %s flags %d mode 0%o\n",
+ dir, ceph_vinop(dir), dentry, dentry,
+ d_unhashed(dentry) ? "unhashed" : "hashed", flags, mode);
if (dentry->d_name.len > NAME_MAX)
return -ENAMETOOLONG;
@@ -878,17 +892,18 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
goto out_req;
if (dn || d_really_is_negative(dentry) || d_is_symlink(dentry)) {
/* make vfs retry on splice, ENOENT, or symlink */
- dout("atomic_open finish_no_open on dn %p\n", dn);
+ doutc(cl, "finish_no_open on dn %p\n", dn);
err = finish_no_open(file, dn);
} else {
if (IS_ENCRYPTED(dir) &&
!fscrypt_has_permitted_context(dir, d_inode(dentry))) {
- pr_warn("Inconsistent encryption context (parent %llx:%llx child %llx:%llx)\n",
+ pr_warn_client(cl,
+ "Inconsistent encryption context (parent %llx:%llx child %llx:%llx)\n",
ceph_vinop(dir), ceph_vinop(d_inode(dentry)));
goto out_req;
}
- dout("atomic_open finish_open on dn %p\n", dn);
+ doutc(cl, "finish_open on dn %p\n", dn);
if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) {
struct inode *newino = d_inode(dentry);
@@ -903,17 +918,19 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
iput(new_inode);
out_ctx:
ceph_release_acl_sec_ctx(&as_ctx);
- dout("atomic_open result=%d\n", err);
+ doutc(cl, "result=%d\n", err);
return err;
}
int ceph_release(struct inode *inode, struct file *file)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
if (S_ISDIR(inode->i_mode)) {
struct ceph_dir_file_info *dfi = file->private_data;
- dout("release inode %p dir file %p\n", inode, file);
+ doutc(cl, "%p %llx.%llx dir file %p\n", inode,
+ ceph_vinop(inode), file);
WARN_ON(!list_empty(&dfi->file_info.rw_contexts));
ceph_put_fmode(ci, dfi->file_info.fmode, 1);
@@ -925,7 +942,8 @@ int ceph_release(struct inode *inode, struct file *file)
kmem_cache_free(ceph_dir_file_cachep, dfi);
} else {
struct ceph_file_info *fi = file->private_data;
- dout("release inode %p regular file %p\n", inode, file);
+ doutc(cl, "%p %llx.%llx regular file %p\n", inode,
+ ceph_vinop(inode), file);
WARN_ON(!list_empty(&fi->rw_contexts));
ceph_fscache_unuse_cookie(inode, file->f_mode & FMODE_WRITE);
@@ -961,6 +979,7 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
{
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
+ struct ceph_client *cl = fsc->client;
struct ceph_osd_client *osdc = &fsc->client->osdc;
ssize_t ret;
u64 off = *ki_pos;
@@ -969,7 +988,8 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
bool sparse = IS_ENCRYPTED(inode) || ceph_test_mount_opt(fsc, SPARSEREAD);
u64 objver = 0;
- dout("sync_read on inode %p %llx~%llx\n", inode, *ki_pos, len);
+ doutc(cl, "on inode %p %llx.%llx %llx~%llx\n", inode,
+ ceph_vinop(inode), *ki_pos, len);
if (ceph_inode_is_shutdown(inode))
return -EIO;
@@ -1004,8 +1024,8 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
/* determine new offset/length if encrypted */
ceph_fscrypt_adjust_off_and_len(inode, &read_off, &read_len);
- dout("sync_read orig %llu~%llu reading %llu~%llu",
- off, len, read_off, read_len);
+ doutc(cl, "orig %llu~%llu reading %llu~%llu", off, len,
+ read_off, read_len);
req = ceph_osdc_new_request(osdc, &ci->i_layout,
ci->i_vino, read_off, &read_len, 0, 1,
@@ -1059,8 +1079,8 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
objver = req->r_version;
i_size = i_size_read(inode);
- dout("sync_read %llu~%llu got %zd i_size %llu%s\n",
- off, len, ret, i_size, (more ? " MORE" : ""));
+ doutc(cl, "%llu~%llu got %zd i_size %llu%s\n", off, len,
+ ret, i_size, (more ? " MORE" : ""));
/* Fix it to go to end of extent map */
if (sparse && ret >= 0)
@@ -1106,8 +1126,8 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
int zlen = min(len - ret, i_size - off - ret);
int zoff = page_off + ret;
- dout("sync_read zero gap %llu~%llu\n",
- off + ret, off + ret + zlen);
+ doutc(cl, "zero gap %llu~%llu\n", off + ret,
+ off + ret + zlen);
ceph_zero_page_vector_range(zoff, zlen, pages);
ret += zlen;
}
@@ -1152,7 +1172,7 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
if (last_objver)
*last_objver = objver;
}
- dout("sync_read result %zd retry_op %d\n", ret, *retry_op);
+ doutc(cl, "result %zd retry_op %d\n", ret, *retry_op);
return ret;
}
@@ -1161,9 +1181,11 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *to,
{
struct file *file = iocb->ki_filp;
struct inode *inode = file_inode(file);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
- dout("sync_read on file %p %llx~%zx %s\n", file, iocb->ki_pos,
- iov_iter_count(to), (file->f_flags & O_DIRECT) ? "O_DIRECT" : "");
+ doutc(cl, "on file %p %llx~%zx %s\n", file, iocb->ki_pos,
+ iov_iter_count(to),
+ (file->f_flags & O_DIRECT) ? "O_DIRECT" : "");
return __ceph_sync_read(inode, &iocb->ki_pos, to, retry_op, NULL);
}
@@ -1191,6 +1213,7 @@ static void ceph_aio_retry_work(struct work_struct *work);
static void ceph_aio_complete(struct inode *inode,
struct ceph_aio_request *aio_req)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
int ret;
@@ -1204,7 +1227,7 @@ static void ceph_aio_complete(struct inode *inode,
if (!ret)
ret = aio_req->total_len;
- dout("ceph_aio_complete %p rc %d\n", inode, ret);
+ doutc(cl, "%p %llx.%llx rc %d\n", inode, ceph_vinop(inode), ret);
if (ret >= 0 && aio_req->write) {
int dirty;
@@ -1243,11 +1266,13 @@ static void ceph_aio_complete_req(struct ceph_osd_request *req)
struct ceph_client_metric *metric = &ceph_sb_to_mdsc(inode->i_sb)->metric;
unsigned int len = osd_data->bvec_pos.iter.bi_size;
bool sparse = (op->op == CEPH_OSD_OP_SPARSE_READ);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
BUG_ON(osd_data->type != CEPH_OSD_DATA_TYPE_BVECS);
BUG_ON(!osd_data->num_bvecs);
- dout("ceph_aio_complete_req %p rc %d bytes %u\n", inode, rc, len);
+ doutc(cl, "req %p inode %p %llx.%llx, rc %d bytes %u\n", req,
+ inode, ceph_vinop(inode), rc, len);
if (rc == -EOLDSNAPC) {
struct ceph_aio_work *aio_work;
@@ -1388,6 +1413,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
struct inode *inode = file_inode(file);
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
+ struct ceph_client *cl = fsc->client;
struct ceph_client_metric *metric = &fsc->mdsc->metric;
struct ceph_vino vino;
struct ceph_osd_request *req;
@@ -1406,9 +1432,9 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
if (write && ceph_snap(file_inode(file)) != CEPH_NOSNAP)
return -EROFS;
- dout("sync_direct_%s on file %p %lld~%u snapc %p seq %lld\n",
- (write ? "write" : "read"), file, pos, (unsigned)count,
- snapc, snapc ? snapc->seq : 0);
+ doutc(cl, "sync_direct_%s on file %p %lld~%u snapc %p seq %lld\n",
+ (write ? "write" : "read"), file, pos, (unsigned)count,
+ snapc, snapc ? snapc->seq : 0);
if (write) {
int ret2;
@@ -1419,7 +1445,8 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
pos >> PAGE_SHIFT,
(pos + count - 1) >> PAGE_SHIFT);
if (ret2 < 0)
- dout("invalidate_inode_pages2_range returned %d\n", ret2);
+ doutc(cl, "invalidate_inode_pages2_range returned %d\n",
+ ret2);
flags = /* CEPH_OSD_FLAG_ORDERSNAP | */ CEPH_OSD_FLAG_WRITE;
} else {
@@ -1615,6 +1642,7 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
struct inode *inode = file_inode(file);
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
+ struct ceph_client *cl = fsc->client;
struct ceph_osd_client *osdc = &fsc->client->osdc;
struct ceph_osd_request *req;
struct page **pages;
@@ -1629,8 +1657,8 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
if (ceph_snap(file_inode(file)) != CEPH_NOSNAP)
return -EROFS;
- dout("sync_write on file %p %lld~%u snapc %p seq %lld\n",
- file, pos, (unsigned)count, snapc, snapc->seq);
+ doutc(cl, "on file %p %lld~%u snapc %p seq %lld\n", file, pos,
+ (unsigned)count, snapc, snapc->seq);
ret = filemap_write_and_wait_range(inode->i_mapping,
pos, pos + count - 1);
@@ -1674,9 +1702,9 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
last = (pos + len) != (write_pos + write_len);
rmw = first || last;
- dout("sync_write ino %llx %lld~%llu adjusted %lld~%llu -- %srmw\n",
- ci->i_vino.ino, pos, len, write_pos, write_len,
- rmw ? "" : "no ");
+ doutc(cl, "ino %llx %lld~%llu adjusted %lld~%llu -- %srmw\n",
+ ci->i_vino.ino, pos, len, write_pos, write_len,
+ rmw ? "" : "no ");
/*
* The data is emplaced into the page as it would be if it were
@@ -1885,7 +1913,7 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
left -= ret;
}
if (ret < 0) {
- dout("sync_write write failed with %d\n", ret);
+ doutc(cl, "write failed with %d\n", ret);
ceph_release_page_vector(pages, num_pages);
break;
}
@@ -1895,7 +1923,7 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
write_pos, write_len,
GFP_KERNEL);
if (ret < 0) {
- dout("encryption failed with %d\n", ret);
+ doutc(cl, "encryption failed with %d\n", ret);
ceph_release_page_vector(pages, num_pages);
break;
}
@@ -1914,7 +1942,7 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
break;
}
- dout("sync_write write op %lld~%llu\n", write_pos, write_len);
+ doutc(cl, "write op %lld~%llu\n", write_pos, write_len);
osd_req_op_extent_osd_data_pages(req, rmw ? 1 : 0, pages, write_len,
offset_in_page(write_pos), false,
true);
@@ -1945,7 +1973,7 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
req->r_end_latency, len, ret);
ceph_osdc_put_request(req);
if (ret != 0) {
- dout("sync_write osd write returned %d\n", ret);
+ doutc(cl, "osd write returned %d\n", ret);
/* Version changed! Must re-do the rmw cycle */
if ((assert_ver && (ret == -ERANGE || ret == -EOVERFLOW)) ||
(!assert_ver && ret == -EEXIST)) {
@@ -1975,13 +2003,13 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
pos >> PAGE_SHIFT,
(pos + len - 1) >> PAGE_SHIFT);
if (ret < 0) {
- dout("invalidate_inode_pages2_range returned %d\n",
- ret);
+ doutc(cl, "invalidate_inode_pages2_range returned %d\n",
+ ret);
ret = 0;
}
pos += len;
written += len;
- dout("sync_write written %d\n", written);
+ doutc(cl, "written %d\n", written);
if (pos > i_size_read(inode)) {
check_caps = ceph_inode_set_size(inode, pos);
if (check_caps)
@@ -1995,7 +2023,7 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
ret = written;
iocb->ki_pos = pos;
}
- dout("sync_write returning %d\n", ret);
+ doutc(cl, "returning %d\n", ret);
return ret;
}
@@ -2014,13 +2042,14 @@ static ssize_t ceph_read_iter(struct kiocb *iocb, struct iov_iter *to)
struct inode *inode = file_inode(filp);
struct ceph_inode_info *ci = ceph_inode(inode);
bool direct_lock = iocb->ki_flags & IOCB_DIRECT;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
ssize_t ret;
int want = 0, got = 0;
int retry_op = 0, read = 0;
again:
- dout("aio_read %p %llx.%llx %llu~%u trying to get caps on %p\n",
- inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len, inode);
+ doutc(cl, "%llu~%u trying to get caps on %p %llx.%llx\n",
+ iocb->ki_pos, (unsigned)len, inode, ceph_vinop(inode));
if (ceph_inode_is_shutdown(inode))
return -ESTALE;
@@ -2048,9 +2077,9 @@ static ssize_t ceph_read_iter(struct kiocb *iocb, struct iov_iter *to)
(iocb->ki_flags & IOCB_DIRECT) ||
(fi->flags & CEPH_F_SYNC)) {
- dout("aio_sync_read %p %llx.%llx %llu~%u got cap refs on %s\n",
- inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len,
- ceph_cap_string(got));
+ doutc(cl, "sync %p %llx.%llx %llu~%u got cap refs on %s\n",
+ inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len,
+ ceph_cap_string(got));
if (!ceph_has_inline_data(ci)) {
if (!retry_op &&
@@ -2068,16 +2097,16 @@ static ssize_t ceph_read_iter(struct kiocb *iocb, struct iov_iter *to)
}
} else {
CEPH_DEFINE_RW_CONTEXT(rw_ctx, got);
- dout("aio_read %p %llx.%llx %llu~%u got cap refs on %s\n",
- inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len,
- ceph_cap_string(got));
+ doutc(cl, "async %p %llx.%llx %llu~%u got cap refs on %s\n",
+ inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len,
+ ceph_cap_string(got));
ceph_add_rw_context(fi, &rw_ctx);
ret = generic_file_read_iter(iocb, to);
ceph_del_rw_context(fi, &rw_ctx);
}
- dout("aio_read %p %llx.%llx dropping cap refs on %s = %d\n",
- inode, ceph_vinop(inode), ceph_cap_string(got), (int)ret);
+ doutc(cl, "%p %llx.%llx dropping cap refs on %s = %d\n",
+ inode, ceph_vinop(inode), ceph_cap_string(got), (int)ret);
ceph_put_cap_refs(ci, got);
if (direct_lock)
@@ -2137,8 +2166,8 @@ static ssize_t ceph_read_iter(struct kiocb *iocb, struct iov_iter *to)
/* hit EOF or hole? */
if (retry_op == CHECK_EOF && iocb->ki_pos < i_size &&
ret < len) {
- dout("sync_read hit hole, ppos %lld < size %lld"
- ", reading more\n", iocb->ki_pos, i_size);
+ doutc(cl, "hit hole, ppos %lld < size %lld, reading more\n",
+ iocb->ki_pos, i_size);
read += ret;
len -= ret;
@@ -2233,6 +2262,7 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
struct inode *inode = file_inode(file);
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
+ struct ceph_client *cl = fsc->client;
struct ceph_osd_client *osdc = &fsc->client->osdc;
struct ceph_cap_flush *prealloc_cf;
ssize_t count, written = 0;
@@ -2300,8 +2330,9 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
if (err)
goto out;
- dout("aio_write %p %llx.%llx %llu~%zd getting caps. i_size %llu\n",
- inode, ceph_vinop(inode), pos, count, i_size_read(inode));
+ doutc(cl, "%p %llx.%llx %llu~%zd getting caps. i_size %llu\n",
+ inode, ceph_vinop(inode), pos, count,
+ i_size_read(inode));
if (!(fi->flags & CEPH_F_SYNC) && !direct_lock)
want |= CEPH_CAP_FILE_BUFFER;
if (fi->fmode & CEPH_FILE_MODE_LAZY)
@@ -2317,8 +2348,8 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
inode_inc_iversion_raw(inode);
- dout("aio_write %p %llx.%llx %llu~%zd got cap refs on %s\n",
- inode, ceph_vinop(inode), pos, count, ceph_cap_string(got));
+ doutc(cl, "%p %llx.%llx %llu~%zd got cap refs on %s\n",
+ inode, ceph_vinop(inode), pos, count, ceph_cap_string(got));
if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 ||
(iocb->ki_flags & IOCB_DIRECT) || (fi->flags & CEPH_F_SYNC) ||
@@ -2378,14 +2409,14 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
ceph_check_caps(ci, CHECK_CAPS_FLUSH);
}
- dout("aio_write %p %llx.%llx %llu~%u dropping cap refs on %s\n",
- inode, ceph_vinop(inode), pos, (unsigned)count,
- ceph_cap_string(got));
+ doutc(cl, "%p %llx.%llx %llu~%u dropping cap refs on %s\n",
+ inode, ceph_vinop(inode), pos, (unsigned)count,
+ ceph_cap_string(got));
ceph_put_cap_refs(ci, got);
if (written == -EOLDSNAPC) {
- dout("aio_write %p %llx.%llx %llu~%u" "got EOLDSNAPC, retrying\n",
- inode, ceph_vinop(inode), pos, (unsigned)count);
+ doutc(cl, "%p %llx.%llx %llu~%u" "got EOLDSNAPC, retrying\n",
+ inode, ceph_vinop(inode), pos, (unsigned)count);
goto retry_snap;
}
@@ -2572,14 +2603,15 @@ static long ceph_fallocate(struct file *file, int mode,
struct inode *inode = file_inode(file);
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_cap_flush *prealloc_cf;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
int want, got = 0;
int dirty;
int ret = 0;
loff_t endoff = 0;
loff_t size;
- dout("%s %p %llx.%llx mode %x, offset %llu length %llu\n", __func__,
- inode, ceph_vinop(inode), mode, offset, length);
+ doutc(cl, "%p %llx.%llx mode %x, offset %llu length %llu\n",
+ inode, ceph_vinop(inode), mode, offset, length);
if (mode != (FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
return -EOPNOTSUPP;
@@ -2708,6 +2740,7 @@ static void put_rd_wr_caps(struct ceph_inode_info *src_ci, int src_got,
static int is_file_size_ok(struct inode *src_inode, struct inode *dst_inode,
loff_t src_off, loff_t dst_off, size_t len)
{
+ struct ceph_client *cl = ceph_inode_to_client(src_inode);
loff_t size, endoff;
size = i_size_read(src_inode);
@@ -2718,8 +2751,8 @@ static int is_file_size_ok(struct inode *src_inode, struct inode *dst_inode,
* inode.
*/
if (src_off + len > size) {
- dout("Copy beyond EOF (%llu + %zu > %llu)\n",
- src_off, len, size);
+ doutc(cl, "Copy beyond EOF (%llu + %zu > %llu)\n", src_off,
+ len, size);
return -EOPNOTSUPP;
}
size = i_size_read(dst_inode);
@@ -2795,6 +2828,7 @@ static ssize_t ceph_do_objects_copy(struct ceph_inode_info *src_ci, u64 *src_off
u64 src_objnum, src_objoff, dst_objnum, dst_objoff;
u32 src_objlen, dst_objlen;
u32 object_size = src_ci->i_layout.object_size;
+ struct ceph_client *cl = fsc->client;
int ret;
src_oloc.pool = src_ci->i_layout.pool_id;
@@ -2836,9 +2870,10 @@ static ssize_t ceph_do_objects_copy(struct ceph_inode_info *src_ci, u64 *src_off
if (ret) {
if (ret == -EOPNOTSUPP) {
fsc->have_copy_from2 = false;
- pr_notice("OSDs don't support copy-from2; disabling copy offload\n");
+ pr_notice_client(cl,
+ "OSDs don't support copy-from2; disabling copy offload\n");
}
- dout("ceph_osdc_copy_from returned %d\n", ret);
+ doutc(cl, "returned %d\n", ret);
if (!bytes)
bytes = ret;
goto out;
@@ -2865,6 +2900,7 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off,
struct ceph_inode_info *dst_ci = ceph_inode(dst_inode);
struct ceph_cap_flush *prealloc_cf;
struct ceph_fs_client *src_fsc = ceph_inode_to_fs_client(src_inode);
+ struct ceph_client *cl = src_fsc->client;
loff_t size;
ssize_t ret = -EIO, bytes;
u64 src_objnum, dst_objnum, src_objoff, dst_objoff;
@@ -2907,7 +2943,7 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off,
(src_ci->i_layout.stripe_count != 1) ||
(dst_ci->i_layout.stripe_count != 1) ||
(src_ci->i_layout.object_size != dst_ci->i_layout.object_size)) {
- dout("Invalid src/dst files layout\n");
+ doutc(cl, "Invalid src/dst files layout\n");
return -EOPNOTSUPP;
}
@@ -2925,12 +2961,12 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off,
/* Start by sync'ing the source and destination files */
ret = file_write_and_wait_range(src_file, src_off, (src_off + len));
if (ret < 0) {
- dout("failed to write src file (%zd)\n", ret);
+ doutc(cl, "failed to write src file (%zd)\n", ret);
goto out;
}
ret = file_write_and_wait_range(dst_file, dst_off, (dst_off + len));
if (ret < 0) {
- dout("failed to write dst file (%zd)\n", ret);
+ doutc(cl, "failed to write dst file (%zd)\n", ret);
goto out;
}
@@ -2942,7 +2978,7 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off,
err = get_rd_wr_caps(src_file, &src_got,
dst_file, (dst_off + len), &dst_got);
if (err < 0) {
- dout("get_rd_wr_caps returned %d\n", err);
+ doutc(cl, "get_rd_wr_caps returned %d\n", err);
ret = -EOPNOTSUPP;
goto out;
}
@@ -2957,7 +2993,8 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off,
dst_off >> PAGE_SHIFT,
(dst_off + len) >> PAGE_SHIFT);
if (ret < 0) {
- dout("Failed to invalidate inode pages (%zd)\n", ret);
+ doutc(cl, "Failed to invalidate inode pages (%zd)\n",
+ ret);
ret = 0; /* XXX */
}
ceph_calc_file_object_mapping(&src_ci->i_layout, src_off,
@@ -2978,7 +3015,7 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off,
* starting at the src_off
*/
if (src_objoff) {
- dout("Initial partial copy of %u bytes\n", src_objlen);
+ doutc(cl, "Initial partial copy of %u bytes\n", src_objlen);
/*
* we need to temporarily drop all caps as we'll be calling
@@ -2989,7 +3026,7 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off,
&dst_off, src_objlen, flags);
/* Abort on short copies or on error */
if (ret < (long)src_objlen) {
- dout("Failed partial copy (%zd)\n", ret);
+ doutc(cl, "Failed partial copy (%zd)\n", ret);
goto out;
}
len -= ret;
@@ -3011,7 +3048,7 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off,
ret = bytes;
goto out_caps;
}
- dout("Copied %zu bytes out of %zu\n", bytes, len);
+ doutc(cl, "Copied %zu bytes out of %zu\n", bytes, len);
len -= bytes;
ret += bytes;
@@ -3039,13 +3076,13 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off,
* there were errors in remote object copies (len >= object_size).
*/
if (len && (len < src_ci->i_layout.object_size)) {
- dout("Final partial copy of %zu bytes\n", len);
+ doutc(cl, "Final partial copy of %zu bytes\n", len);
bytes = do_splice_direct(src_file, &src_off, dst_file,
&dst_off, len, flags);
if (bytes > 0)
ret += bytes;
else
- dout("Failed partial copy (%zd)\n", bytes);
+ doutc(cl, "Failed partial copy (%zd)\n", bytes);
}
out:
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index f0befbeb6cb8..c4632a823a5b 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -129,6 +129,8 @@ void ceph_as_ctx_to_req(struct ceph_mds_request *req,
struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino,
struct inode *newino)
{
+ struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(sb);
+ struct ceph_client *cl = mdsc->fsc->client;
struct inode *inode;
if (ceph_vino_is_reserved(vino))
@@ -145,12 +147,13 @@ struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino,
}
if (!inode) {
- dout("No inode found for %llx.%llx\n", vino.ino, vino.snap);
+ doutc(cl, "no inode found for %llx.%llx\n", vino.ino, vino.snap);
return ERR_PTR(-ENOMEM);
}
- dout("get_inode on %llu=%llx.%llx got %p new %d\n", ceph_present_inode(inode),
- ceph_vinop(inode), inode, !!(inode->i_state & I_NEW));
+ doutc(cl, "on %llx=%llx.%llx got %p new %d\n",
+ ceph_present_inode(inode), ceph_vinop(inode), inode,
+ !!(inode->i_state & I_NEW));
return inode;
}
@@ -159,6 +162,7 @@ struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino,
*/
struct inode *ceph_get_snapdir(struct inode *parent)
{
+ struct ceph_client *cl = ceph_inode_to_client(parent);
struct ceph_vino vino = {
.ino = ceph_ino(parent),
.snap = CEPH_SNAPDIR,
@@ -171,14 +175,14 @@ struct inode *ceph_get_snapdir(struct inode *parent)
return inode;
if (!S_ISDIR(parent->i_mode)) {
- pr_warn_once("bad snapdir parent type (mode=0%o)\n",
- parent->i_mode);
+ pr_warn_once_client(cl, "bad snapdir parent type (mode=0%o)\n",
+ parent->i_mode);
goto err;
}
if (!(inode->i_state & I_NEW) && !S_ISDIR(inode->i_mode)) {
- pr_warn_once("bad snapdir inode type (mode=0%o)\n",
- inode->i_mode);
+ pr_warn_once_client(cl, "bad snapdir inode type (mode=0%o)\n",
+ inode->i_mode);
goto err;
}
@@ -203,7 +207,7 @@ struct inode *ceph_get_snapdir(struct inode *parent)
inode->i_flags |= S_ENCRYPTED;
ci->fscrypt_auth_len = pci->fscrypt_auth_len;
} else {
- dout("Failed to alloc snapdir fscrypt_auth\n");
+ doutc(cl, "Failed to alloc snapdir fscrypt_auth\n");
ret = -ENOMEM;
goto err;
}
@@ -249,6 +253,8 @@ const struct inode_operations ceph_file_iops = {
static struct ceph_inode_frag *__get_or_create_frag(struct ceph_inode_info *ci,
u32 f)
{
+ struct inode *inode = &ci->netfs.inode;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct rb_node **p;
struct rb_node *parent = NULL;
struct ceph_inode_frag *frag;
@@ -279,8 +285,7 @@ static struct ceph_inode_frag *__get_or_create_frag(struct ceph_inode_info *ci,
rb_link_node(&frag->node, parent, p);
rb_insert_color(&frag->node, &ci->i_fragtree);
- dout("get_or_create_frag added %llx.%llx frag %x\n",
- ceph_vinop(&ci->netfs.inode), f);
+ doutc(cl, "added %p %llx.%llx frag %x\n", inode, ceph_vinop(inode), f);
return frag;
}
@@ -313,6 +318,7 @@ struct ceph_inode_frag *__ceph_find_frag(struct ceph_inode_info *ci, u32 f)
static u32 __ceph_choose_frag(struct ceph_inode_info *ci, u32 v,
struct ceph_inode_frag *pfrag, int *found)
{
+ struct ceph_client *cl = ceph_inode_to_client(&ci->netfs.inode);
u32 t = ceph_frag_make(0, 0);
struct ceph_inode_frag *frag;
unsigned nway, i;
@@ -336,8 +342,8 @@ static u32 __ceph_choose_frag(struct ceph_inode_info *ci, u32 v,
/* choose child */
nway = 1 << frag->split_by;
- dout("choose_frag(%x) %x splits by %d (%d ways)\n", v, t,
- frag->split_by, nway);
+ doutc(cl, "frag(%x) %x splits by %d (%d ways)\n", v, t,
+ frag->split_by, nway);
for (i = 0; i < nway; i++) {
n = ceph_frag_make_child(t, frag->split_by, i);
if (ceph_frag_contains_value(n, v)) {
@@ -347,7 +353,7 @@ static u32 __ceph_choose_frag(struct ceph_inode_info *ci, u32 v,
}
BUG_ON(i == nway);
}
- dout("choose_frag(%x) = %x\n", v, t);
+ doutc(cl, "frag(%x) = %x\n", v, t);
return t;
}
@@ -371,6 +377,7 @@ static int ceph_fill_dirfrag(struct inode *inode,
struct ceph_mds_reply_dirfrag *dirinfo)
{
struct ceph_inode_info *ci = ceph_inode(inode);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_frag *frag;
u32 id = le32_to_cpu(dirinfo->frag);
int mds = le32_to_cpu(dirinfo->auth);
@@ -395,14 +402,14 @@ static int ceph_fill_dirfrag(struct inode *inode,
goto out;
if (frag->split_by == 0) {
/* tree leaf, remove */
- dout("fill_dirfrag removed %llx.%llx frag %x"
- " (no ref)\n", ceph_vinop(inode), id);
+ doutc(cl, "removed %p %llx.%llx frag %x (no ref)\n",
+ inode, ceph_vinop(inode), id);
rb_erase(&frag->node, &ci->i_fragtree);
kfree(frag);
} else {
/* tree branch, keep and clear */
- dout("fill_dirfrag cleared %llx.%llx frag %x"
- " referral\n", ceph_vinop(inode), id);
+ doutc(cl, "cleared %p %llx.%llx frag %x referral\n",
+ inode, ceph_vinop(inode), id);
frag->mds = -1;
frag->ndist = 0;
}
@@ -415,8 +422,9 @@ static int ceph_fill_dirfrag(struct inode *inode,
if (IS_ERR(frag)) {
/* this is not the end of the world; we can continue
with bad/inaccurate delegation info */
- pr_err("fill_dirfrag ENOMEM on mds ref %llx.%llx fg %x\n",
- ceph_vinop(inode), le32_to_cpu(dirinfo->frag));
+ pr_err_client(cl, "ENOMEM on mds ref %p %llx.%llx fg %x\n",
+ inode, ceph_vinop(inode),
+ le32_to_cpu(dirinfo->frag));
err = -ENOMEM;
goto out;
}
@@ -425,8 +433,8 @@ static int ceph_fill_dirfrag(struct inode *inode,
frag->ndist = min_t(u32, ndist, CEPH_MAX_DIRFRAG_REP);
for (i = 0; i < frag->ndist; i++)
frag->dist[i] = le32_to_cpu(dirinfo->dist[i]);
- dout("fill_dirfrag %llx.%llx frag %x ndist=%d\n",
- ceph_vinop(inode), frag->frag, frag->ndist);
+ doutc(cl, "%p %llx.%llx frag %x ndist=%d\n", inode,
+ ceph_vinop(inode), frag->frag, frag->ndist);
out:
mutex_unlock(&ci->i_fragtree_mutex);
@@ -454,6 +462,7 @@ static int ceph_fill_fragtree(struct inode *inode,
struct ceph_frag_tree_head *fragtree,
struct ceph_mds_reply_dirfrag *dirinfo)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_inode_frag *frag, *prev_frag = NULL;
struct rb_node *rb_node;
@@ -489,15 +498,15 @@ static int ceph_fill_fragtree(struct inode *inode,
frag_tree_split_cmp, NULL);
}
- dout("fill_fragtree %llx.%llx\n", ceph_vinop(inode));
+ doutc(cl, "%p %llx.%llx\n", inode, ceph_vinop(inode));
rb_node = rb_first(&ci->i_fragtree);
for (i = 0; i < nsplits; i++) {
id = le32_to_cpu(fragtree->splits[i].frag);
split_by = le32_to_cpu(fragtree->splits[i].by);
if (split_by == 0 || ceph_frag_bits(id) + split_by > 24) {
- pr_err("fill_fragtree %llx.%llx invalid split %d/%u, "
- "frag %x split by %d\n", ceph_vinop(inode),
- i, nsplits, id, split_by);
+ pr_err_client(cl, "%p %llx.%llx invalid split %d/%u, "
+ "frag %x split by %d\n", inode,
+ ceph_vinop(inode), i, nsplits, id, split_by);
continue;
}
frag = NULL;
@@ -529,7 +538,7 @@ static int ceph_fill_fragtree(struct inode *inode,
if (frag->split_by == 0)
ci->i_fragtree_nsplits++;
frag->split_by = split_by;
- dout(" frag %x split by %d\n", frag->frag, frag->split_by);
+ doutc(cl, " frag %x split by %d\n", frag->frag, frag->split_by);
prev_frag = frag;
}
while (rb_node) {
@@ -554,6 +563,7 @@ static int ceph_fill_fragtree(struct inode *inode,
*/
struct inode *ceph_alloc_inode(struct super_block *sb)
{
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb);
struct ceph_inode_info *ci;
int i;
@@ -561,7 +571,7 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
if (!ci)
return NULL;
- dout("alloc_inode %p\n", &ci->netfs.inode);
+ doutc(fsc->client, "%p\n", &ci->netfs.inode);
/* Set parameters for the netfs library */
netfs_inode_init(&ci->netfs, &ceph_netfs_ops);
@@ -675,10 +685,11 @@ void ceph_evict_inode(struct inode *inode)
{
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_frag *frag;
struct rb_node *n;
- dout("evict_inode %p ino %llx.%llx\n", inode, ceph_vinop(inode));
+ doutc(cl, "%p ino %llx.%llx\n", inode, ceph_vinop(inode));
percpu_counter_dec(&mdsc->metric.total_inodes);
@@ -701,8 +712,8 @@ void ceph_evict_inode(struct inode *inode)
*/
if (ci->i_snap_realm) {
if (ceph_snap(inode) == CEPH_NOSNAP) {
- dout(" dropping residual ref to snap realm %p\n",
- ci->i_snap_realm);
+ doutc(cl, " dropping residual ref to snap realm %p\n",
+ ci->i_snap_realm);
ceph_change_snap_realm(inode, NULL);
} else {
ceph_put_snapid_map(mdsc, ci->i_snapid_map);
@@ -743,15 +754,16 @@ static inline blkcnt_t calc_inode_blocks(u64 size)
int ceph_fill_file_size(struct inode *inode, int issued,
u32 truncate_seq, u64 truncate_size, u64 size)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
int queue_trunc = 0;
loff_t isize = i_size_read(inode);
if (ceph_seq_cmp(truncate_seq, ci->i_truncate_seq) > 0 ||
(truncate_seq == ci->i_truncate_seq && size > isize)) {
- dout("size %lld -> %llu\n", isize, size);
+ doutc(cl, "size %lld -> %llu\n", isize, size);
if (size > 0 && S_ISDIR(inode->i_mode)) {
- pr_err("fill_file_size non-zero size for directory\n");
+ pr_err_client(cl, "non-zero size for directory\n");
size = 0;
}
i_size_write(inode, size);
@@ -764,8 +776,8 @@ int ceph_fill_file_size(struct inode *inode, int issued,
ceph_fscache_update(inode);
ci->i_reported_size = size;
if (truncate_seq != ci->i_truncate_seq) {
- dout("%s truncate_seq %u -> %u\n", __func__,
- ci->i_truncate_seq, truncate_seq);
+ doutc(cl, "truncate_seq %u -> %u\n",
+ ci->i_truncate_seq, truncate_seq);
ci->i_truncate_seq = truncate_seq;
/* the MDS should have revoked these caps */
@@ -794,14 +806,15 @@ int ceph_fill_file_size(struct inode *inode, int issued,
* anyway.
*/
if (ceph_seq_cmp(truncate_seq, ci->i_truncate_seq) >= 0) {
- dout("%s truncate_size %lld -> %llu, encrypted %d\n", __func__,
- ci->i_truncate_size, truncate_size, !!IS_ENCRYPTED(inode));
+ doutc(cl, "truncate_size %lld -> %llu, encrypted %d\n",
+ ci->i_truncate_size, truncate_size,
+ !!IS_ENCRYPTED(inode));
ci->i_truncate_size = truncate_size;
if (IS_ENCRYPTED(inode)) {
- dout("%s truncate_pagecache_size %lld -> %llu\n",
- __func__, ci->i_truncate_pagecache_size, size);
+ doutc(cl, "truncate_pagecache_size %lld -> %llu\n",
+ ci->i_truncate_pagecache_size, size);
ci->i_truncate_pagecache_size = size;
} else {
ci->i_truncate_pagecache_size = truncate_size;
@@ -814,6 +827,7 @@ void ceph_fill_file_time(struct inode *inode, int issued,
u64 time_warp_seq, struct timespec64 *ctime,
struct timespec64 *mtime, struct timespec64 *atime)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
struct timespec64 ictime = inode_get_ctime(inode);
int warn = 0;
@@ -825,7 +839,7 @@ void ceph_fill_file_time(struct inode *inode, int issued,
CEPH_CAP_XATTR_EXCL)) {
if (ci->i_version == 0 ||
timespec64_compare(ctime, &ictime) > 0) {
- dout("ctime %lld.%09ld -> %lld.%09ld inc w/ cap\n",
+ doutc(cl, "ctime %lld.%09ld -> %lld.%09ld inc w/ cap\n",
ictime.tv_sec, ictime.tv_nsec,
ctime->tv_sec, ctime->tv_nsec);
inode_set_ctime_to_ts(inode, *ctime);
@@ -833,11 +847,10 @@ void ceph_fill_file_time(struct inode *inode, int issued,
if (ci->i_version == 0 ||
ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) > 0) {
/* the MDS did a utimes() */
- dout("mtime %lld.%09ld -> %lld.%09ld "
- "tw %d -> %d\n",
- inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
- mtime->tv_sec, mtime->tv_nsec,
- ci->i_time_warp_seq, (int)time_warp_seq);
+ doutc(cl, "mtime %lld.%09ld -> %lld.%09ld tw %d -> %d\n",
+ inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
+ mtime->tv_sec, mtime->tv_nsec,
+ ci->i_time_warp_seq, (int)time_warp_seq);
inode->i_mtime = *mtime;
inode->i_atime = *atime;
@@ -845,17 +858,17 @@ void ceph_fill_file_time(struct inode *inode, int issued,
} else if (time_warp_seq == ci->i_time_warp_seq) {
/* nobody did utimes(); take the max */
if (timespec64_compare(mtime, &inode->i_mtime) > 0) {
- dout("mtime %lld.%09ld -> %lld.%09ld inc\n",
- inode->i_mtime.tv_sec,
- inode->i_mtime.tv_nsec,
- mtime->tv_sec, mtime->tv_nsec);
+ doutc(cl, "mtime %lld.%09ld -> %lld.%09ld inc\n",
+ inode->i_mtime.tv_sec,
+ inode->i_mtime.tv_nsec,
+ mtime->tv_sec, mtime->tv_nsec);
inode->i_mtime = *mtime;
}
if (timespec64_compare(atime, &inode->i_atime) > 0) {
- dout("atime %lld.%09ld -> %lld.%09ld inc\n",
- inode->i_atime.tv_sec,
- inode->i_atime.tv_nsec,
- atime->tv_sec, atime->tv_nsec);
+ doutc(cl, "atime %lld.%09ld -> %lld.%09ld inc\n",
+ inode->i_atime.tv_sec,
+ inode->i_atime.tv_nsec,
+ atime->tv_sec, atime->tv_nsec);
inode->i_atime = *atime;
}
} else if (issued & CEPH_CAP_FILE_EXCL) {
@@ -875,13 +888,16 @@ void ceph_fill_file_time(struct inode *inode, int issued,
}
}
if (warn) /* time_warp_seq shouldn't go backwards */
- dout("%p mds time_warp_seq %llu < %u\n",
- inode, time_warp_seq, ci->i_time_warp_seq);
+ doutc(cl, "%p mds time_warp_seq %llu < %u\n", inode,
+ time_warp_seq, ci->i_time_warp_seq);
}
#if IS_ENABLED(CONFIG_FS_ENCRYPTION)
-static int decode_encrypted_symlink(const char *encsym, int enclen, u8 **decsym)
+static int decode_encrypted_symlink(struct ceph_mds_client *mdsc,
+ const char *encsym,
+ int enclen, u8 **decsym)
{
+ struct ceph_client *cl = mdsc->fsc->client;
int declen;
u8 *sym;
@@ -891,8 +907,9 @@ static int decode_encrypted_symlink(const char *encsym, int enclen, u8 **decsym)
declen = ceph_base64_decode(encsym, enclen, sym);
if (declen < 0) {
- pr_err("%s: can't decode symlink (%d). Content: %.*s\n",
- __func__, declen, enclen, encsym);
+ pr_err_client(cl,
+ "can't decode symlink (%d). Content: %.*s\n",
+ declen, enclen, encsym);
kfree(sym);
return -EIO;
}
@@ -901,7 +918,9 @@ static int decode_encrypted_symlink(const char *encsym, int enclen, u8 **decsym)
return declen;
}
#else
-static int decode_encrypted_symlink(const char *encsym, int symlen, u8 **decsym)
+static int decode_encrypted_symlink(struct ceph_mds_client *mdsc,
+ const char *encsym,
+ int symlen, u8 **decsym)
{
return -EOPNOTSUPP;
}
@@ -918,6 +937,7 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
struct ceph_cap_reservation *caps_reservation)
{
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mds_reply_inode *info = iinfo->in;
struct ceph_inode_info *ci = ceph_inode(inode);
int issued, new_issued, info_caps;
@@ -936,25 +956,26 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
lockdep_assert_held(&mdsc->snap_rwsem);
- dout("%s %p ino %llx.%llx v %llu had %llu\n", __func__,
- inode, ceph_vinop(inode), le64_to_cpu(info->version),
- ci->i_version);
+ doutc(cl, "%p ino %llx.%llx v %llu had %llu\n", inode, ceph_vinop(inode),
+ le64_to_cpu(info->version), ci->i_version);
/* Once I_NEW is cleared, we can't change type or dev numbers */
if (inode->i_state & I_NEW) {
inode->i_mode = mode;
} else {
if (inode_wrong_type(inode, mode)) {
- pr_warn_once("inode type changed! (ino %llx.%llx is 0%o, mds says 0%o)\n",
- ceph_vinop(inode), inode->i_mode, mode);
+ pr_warn_once_client(cl,
+ "inode type changed! (ino %llx.%llx is 0%o, mds says 0%o)\n",
+ ceph_vinop(inode), inode->i_mode, mode);
return -ESTALE;
}
if ((S_ISCHR(mode) || S_ISBLK(mode)) && inode->i_rdev != rdev) {
- pr_warn_once("dev inode rdev changed! (ino %llx.%llx is %u:%u, mds says %u:%u)\n",
- ceph_vinop(inode), MAJOR(inode->i_rdev),
- MINOR(inode->i_rdev), MAJOR(rdev),
- MINOR(rdev));
+ pr_warn_once_client(cl,
+ "dev inode rdev changed! (ino %llx.%llx is %u:%u, mds says %u:%u)\n",
+ ceph_vinop(inode), MAJOR(inode->i_rdev),
+ MINOR(inode->i_rdev), MAJOR(rdev),
+ MINOR(rdev));
return -ESTALE;
}
}
@@ -976,8 +997,8 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
if (iinfo->xattr_len > 4) {
xattr_blob = ceph_buffer_new(iinfo->xattr_len, GFP_NOFS);
if (!xattr_blob)
- pr_err("%s ENOMEM xattr blob %d bytes\n", __func__,
- iinfo->xattr_len);
+ pr_err_client(cl, "ENOMEM xattr blob %d bytes\n",
+ iinfo->xattr_len);
}
if (iinfo->pool_ns_len > 0)
@@ -1031,9 +1052,10 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
inode->i_mode = mode;
inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(info->uid));
inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(info->gid));
- dout("%p mode 0%o uid.gid %d.%d\n", inode, inode->i_mode,
- from_kuid(&init_user_ns, inode->i_uid),
- from_kgid(&init_user_ns, inode->i_gid));
+ doutc(cl, "%p %llx.%llx mode 0%o uid.gid %d.%d\n", inode,
+ ceph_vinop(inode), inode->i_mode,
+ from_kuid(&init_user_ns, inode->i_uid),
+ from_kgid(&init_user_ns, inode->i_gid));
ceph_decode_timespec64(&ci->i_btime, &iinfo->btime);
ceph_decode_timespec64(&ci->i_snap_btime, &iinfo->snap_btime);
}
@@ -1089,7 +1111,8 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
if (size == round_up(fsize, CEPH_FSCRYPT_BLOCK_SIZE)) {
size = fsize;
} else {
- pr_warn("fscrypt size mismatch: size=%llu fscrypt_file=%llu, discarding fscrypt_file size.\n",
+ pr_warn_client(cl,
+ "fscrypt size mismatch: size=%llu fscrypt_file=%llu, discarding fscrypt_file size.\n",
info->size, size);
}
}
@@ -1101,8 +1124,8 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
/* only update max_size on auth cap */
if ((info->cap.flags & CEPH_CAP_FLAG_AUTH) &&
ci->i_max_size != le64_to_cpu(info->max_size)) {
- dout("max_size %lld -> %llu\n", ci->i_max_size,
- le64_to_cpu(info->max_size));
+ doutc(cl, "max_size %lld -> %llu\n",
+ ci->i_max_size, le64_to_cpu(info->max_size));
ci->i_max_size = le64_to_cpu(info->max_size);
}
}
@@ -1165,15 +1188,17 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
if (IS_ENCRYPTED(inode)) {
if (symlen != i_size_read(inode))
- pr_err("%s %llx.%llx BAD symlink size %lld\n",
- __func__, ceph_vinop(inode),
+ pr_err_client(cl,
+ "%p %llx.%llx BAD symlink size %lld\n",
+ inode, ceph_vinop(inode),
i_size_read(inode));
- err = decode_encrypted_symlink(iinfo->symlink,
+ err = decode_encrypted_symlink(mdsc, iinfo->symlink,
symlen, (u8 **)&sym);
if (err < 0) {
- pr_err("%s decoding encrypted symlink failed: %d\n",
- __func__, err);
+ pr_err_client(cl,
+ "decoding encrypted symlink failed: %d\n",
+ err);
goto out;
}
symlen = err;
@@ -1181,8 +1206,9 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
inode->i_blocks = calc_inode_blocks(symlen);
} else {
if (symlen != i_size_read(inode)) {
- pr_err("%s %llx.%llx BAD symlink size %lld\n",
- __func__, ceph_vinop(inode),
+ pr_err_client(cl,
+ "%p %llx.%llx BAD symlink size %lld\n",
+ inode, ceph_vinop(inode),
i_size_read(inode));
i_size_write(inode, symlen);
inode->i_blocks = calc_inode_blocks(symlen);
@@ -1217,8 +1243,8 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
inode->i_fop = &ceph_dir_fops;
break;
default:
- pr_err("%s %llx.%llx BAD mode 0%o\n", __func__,
- ceph_vinop(inode), inode->i_mode);
+ pr_err_client(cl, "%p %llx.%llx BAD mode 0%o\n", inode,
+ ceph_vinop(inode), inode->i_mode);
}
/* were we issued a capability? */
@@ -1239,7 +1265,8 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
(info_caps & CEPH_CAP_FILE_SHARED) &&
(issued & CEPH_CAP_FILE_EXCL) == 0 &&
!__ceph_dir_is_complete(ci)) {
- dout(" marking %p complete (empty)\n", inode);
+ doutc(cl, " marking %p complete (empty)\n",
+ inode);
i_size_write(inode, 0);
__ceph_dir_set_complete(ci,
atomic64_read(&ci->i_release_count),
@@ -1248,8 +1275,8 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
wake = true;
} else {
- dout(" %p got snap_caps %s\n", inode,
- ceph_cap_string(info_caps));
+ doutc(cl, " %p got snap_caps %s\n", inode,
+ ceph_cap_string(info_caps));
ci->i_snap_caps |= info_caps;
}
}
@@ -1265,8 +1292,8 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
if (cap_fmode >= 0) {
if (!info_caps)
- pr_warn("mds issued no caps on %llx.%llx\n",
- ceph_vinop(inode));
+ pr_warn_client(cl, "mds issued no caps on %llx.%llx\n",
+ ceph_vinop(inode));
__ceph_touch_fmode(ci, mdsc, cap_fmode);
}
@@ -1312,14 +1339,14 @@ static void __update_dentry_lease(struct inode *dir, struct dentry *dentry,
unsigned long from_time,
struct ceph_mds_session **old_lease_session)
{
+ struct ceph_client *cl = ceph_inode_to_client(dir);
struct ceph_dentry_info *di = ceph_dentry(dentry);
unsigned mask = le16_to_cpu(lease->mask);
long unsigned duration = le32_to_cpu(lease->duration_ms);
long unsigned ttl = from_time + (duration * HZ) / 1000;
long unsigned half_ttl = from_time + (duration * HZ / 2) / 1000;
- dout("update_dentry_lease %p duration %lu ms ttl %lu\n",
- dentry, duration, ttl);
+ doutc(cl, "%p duration %lu ms ttl %lu\n", dentry, duration, ttl);
/* only track leases on regular dentries */
if (ceph_snap(dir) != CEPH_NOSNAP)
@@ -1420,6 +1447,7 @@ static void update_dentry_lease_careful(struct dentry *dentry,
*/
static int splice_dentry(struct dentry **pdn, struct inode *in)
{
+ struct ceph_client *cl = ceph_inode_to_client(in);
struct dentry *dn = *pdn;
struct dentry *realdn;
@@ -1451,23 +1479,21 @@ static int splice_dentry(struct dentry **pdn, struct inode *in)
d_drop(dn);
realdn = d_splice_alias(in, dn);
if (IS_ERR(realdn)) {
- pr_err("splice_dentry error %ld %p inode %p ino %llx.%llx\n",
- PTR_ERR(realdn), dn, in, ceph_vinop(in));
+ pr_err_client(cl, "error %ld %p inode %p ino %llx.%llx\n",
+ PTR_ERR(realdn), dn, in, ceph_vinop(in));
return PTR_ERR(realdn);
}
if (realdn) {
- dout("dn %p (%d) spliced with %p (%d) "
- "inode %p ino %llx.%llx\n",
- dn, d_count(dn),
- realdn, d_count(realdn),
- d_inode(realdn), ceph_vinop(d_inode(realdn)));
+ doutc(cl, "dn %p (%d) spliced with %p (%d) inode %p ino %llx.%llx\n",
+ dn, d_count(dn), realdn, d_count(realdn),
+ d_inode(realdn), ceph_vinop(d_inode(realdn)));
dput(dn);
*pdn = realdn;
} else {
BUG_ON(!ceph_dentry(dn));
- dout("dn %p attached to %p ino %llx.%llx\n",
- dn, d_inode(dn), ceph_vinop(d_inode(dn)));
+ doutc(cl, "dn %p attached to %p ino %llx.%llx\n", dn,
+ d_inode(dn), ceph_vinop(d_inode(dn)));
}
return 0;
}
@@ -1490,13 +1516,14 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req)
struct inode *in = NULL;
struct ceph_vino tvino, dvino;
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb);
+ struct ceph_client *cl = fsc->client;
int err = 0;
- dout("fill_trace %p is_dentry %d is_target %d\n", req,
- rinfo->head->is_dentry, rinfo->head->is_target);
+ doutc(cl, "%p is_dentry %d is_target %d\n", req,
+ rinfo->head->is_dentry, rinfo->head->is_target);
if (!rinfo->head->is_target && !rinfo->head->is_dentry) {
- dout("fill_trace reply is empty!\n");
+ doutc(cl, "reply is empty!\n");
if (rinfo->head->result == 0 && req->r_parent)
ceph_invalidate_dir_request(req);
return 0;
@@ -1553,13 +1580,13 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req)
tvino.snap = le64_to_cpu(rinfo->targeti.in->snapid);
retry_lookup:
dn = d_lookup(parent, &dname);
- dout("d_lookup on parent=%p name=%.*s got %p\n",
- parent, dname.len, dname.name, dn);
+ doutc(cl, "d_lookup on parent=%p name=%.*s got %p\n",
+ parent, dname.len, dname.name, dn);
if (!dn) {
dn = d_alloc(parent, &dname);
- dout("d_alloc %p '%.*s' = %p\n", parent,
- dname.len, dname.name, dn);
+ doutc(cl, "d_alloc %p '%.*s' = %p\n", parent,
+ dname.len, dname.name, dn);
if (!dn) {
dput(parent);
ceph_fname_free_buffer(dir, &oname);
@@ -1575,8 +1602,8 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req)
} else if (d_really_is_positive(dn) &&
(ceph_ino(d_inode(dn)) != tvino.ino ||
ceph_snap(d_inode(dn)) != tvino.snap)) {
- dout(" dn %p points to wrong inode %p\n",
- dn, d_inode(dn));
+ doutc(cl, " dn %p points to wrong inode %p\n",
+ dn, d_inode(dn));
ceph_dir_clear_ordered(dir);
d_delete(dn);
dput(dn);
@@ -1601,8 +1628,8 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req)
rinfo->head->result == 0) ? req->r_fmode : -1,
&req->r_caps_reservation);
if (err < 0) {
- pr_err("ceph_fill_inode badness %p %llx.%llx\n",
- in, ceph_vinop(in));
+ pr_err_client(cl, "badness %p %llx.%llx\n", in,
+ ceph_vinop(in));
req->r_target_inode = NULL;
if (in->i_state & I_NEW)
discard_new_inode(in);
@@ -1652,36 +1679,32 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req)
have_lease = have_dir_cap ||
le32_to_cpu(rinfo->dlease->duration_ms);
if (!have_lease)
- dout("fill_trace no dentry lease or dir cap\n");
+ doutc(cl, "no dentry lease or dir cap\n");
/* rename? */
if (req->r_old_dentry && req->r_op == CEPH_MDS_OP_RENAME) {
struct inode *olddir = req->r_old_dentry_dir;
BUG_ON(!olddir);
- dout(" src %p '%pd' dst %p '%pd'\n",
- req->r_old_dentry,
- req->r_old_dentry,
- dn, dn);
- dout("fill_trace doing d_move %p -> %p\n",
- req->r_old_dentry, dn);
+ doutc(cl, " src %p '%pd' dst %p '%pd'\n",
+ req->r_old_dentry, req->r_old_dentry, dn, dn);
+ doutc(cl, "doing d_move %p -> %p\n", req->r_old_dentry, dn);
/* d_move screws up sibling dentries' offsets */
ceph_dir_clear_ordered(dir);
ceph_dir_clear_ordered(olddir);
d_move(req->r_old_dentry, dn);
- dout(" src %p '%pd' dst %p '%pd'\n",
- req->r_old_dentry,
- req->r_old_dentry,
- dn, dn);
+ doutc(cl, " src %p '%pd' dst %p '%pd'\n",
+ req->r_old_dentry, req->r_old_dentry, dn, dn);
/* ensure target dentry is invalidated, despite
rehashing bug in vfs_rename_dir */
ceph_invalidate_dentry_lease(dn);
- dout("dn %p gets new offset %lld\n", req->r_old_dentry,
- ceph_dentry(req->r_old_dentry)->offset);
+ doutc(cl, "dn %p gets new offset %lld\n",
+ req->r_old_dentry,
+ ceph_dentry(req->r_old_dentry)->offset);
/* swap r_dentry and r_old_dentry in case that
* splice_dentry() gets called later. This is safe
@@ -1693,9 +1716,9 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req)
/* null dentry? */
if (!rinfo->head->is_target) {
- dout("fill_trace null dentry\n");
+ doutc(cl, "null dentry\n");
if (d_really_is_positive(dn)) {
- dout("d_delete %p\n", dn);
+ doutc(cl, "d_delete %p\n", dn);
ceph_dir_clear_ordered(dir);
d_delete(dn);
} else if (have_lease) {
@@ -1719,9 +1742,9 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req)
goto done;
dn = req->r_dentry; /* may have spliced */
} else if (d_really_is_positive(dn) && d_inode(dn) != in) {
- dout(" %p links to %p %llx.%llx, not %llx.%llx\n",
- dn, d_inode(dn), ceph_vinop(d_inode(dn)),
- ceph_vinop(in));
+ doutc(cl, " %p links to %p %llx.%llx, not %llx.%llx\n",
+ dn, d_inode(dn), ceph_vinop(d_inode(dn)),
+ ceph_vinop(in));
d_invalidate(dn);
have_lease = false;
}
@@ -1731,7 +1754,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req)
rinfo->dlease, session,
req->r_request_started);
}
- dout(" final dn %p\n", dn);
+ doutc(cl, " final dn %p\n", dn);
} else if ((req->r_op == CEPH_MDS_OP_LOOKUPSNAP ||
req->r_op == CEPH_MDS_OP_MKSNAP) &&
test_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags) &&
@@ -1742,7 +1765,8 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req)
BUG_ON(!dir);
BUG_ON(ceph_snap(dir) != CEPH_SNAPDIR);
BUG_ON(!req->r_dentry);
- dout(" linking snapped dir %p to dn %p\n", in, req->r_dentry);
+ doutc(cl, " linking snapped dir %p to dn %p\n", in,
+ req->r_dentry);
ceph_dir_clear_ordered(dir);
ihold(in);
err = splice_dentry(&req->r_dentry, in);
@@ -1764,7 +1788,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req)
&dvino, ptvino);
}
done:
- dout("fill_trace done err=%d\n", err);
+ doutc(cl, "done err=%d\n", err);
return err;
}
@@ -1775,6 +1799,7 @@ static int readdir_prepopulate_inodes_only(struct ceph_mds_request *req,
struct ceph_mds_session *session)
{
struct ceph_mds_reply_info_parsed *rinfo = &req->r_reply_info;
+ struct ceph_client *cl = session->s_mdsc->fsc->client;
int i, err = 0;
for (i = 0; i < rinfo->dir_nr; i++) {
@@ -1789,14 +1814,14 @@ static int readdir_prepopulate_inodes_only(struct ceph_mds_request *req,
in = ceph_get_inode(req->r_dentry->d_sb, vino, NULL);
if (IS_ERR(in)) {
err = PTR_ERR(in);
- dout("new_inode badness got %d\n", err);
+ doutc(cl, "badness got %d\n", err);
continue;
}
rc = ceph_fill_inode(in, NULL, &rde->inode, NULL, session,
-1, &req->r_caps_reservation);
if (rc < 0) {
- pr_err("ceph_fill_inode badness on %p got %d\n",
- in, rc);
+ pr_err_client(cl, "inode badness on %p got %d\n", in,
+ rc);
err = rc;
if (in->i_state & I_NEW) {
ihold(in);
@@ -1825,6 +1850,7 @@ static int fill_readdir_cache(struct inode *dir, struct dentry *dn,
struct ceph_readdir_cache_control *ctl,
struct ceph_mds_request *req)
{
+ struct ceph_client *cl = ceph_inode_to_client(dir);
struct ceph_inode_info *ci = ceph_inode(dir);
unsigned nsize = PAGE_SIZE / sizeof(struct dentry*);
unsigned idx = ctl->index % nsize;
@@ -1850,11 +1876,11 @@ static int fill_readdir_cache(struct inode *dir, struct dentry *dn,
if (req->r_dir_release_cnt == atomic64_read(&ci->i_release_count) &&
req->r_dir_ordered_cnt == atomic64_read(&ci->i_ordered_count)) {
- dout("readdir cache dn %p idx %d\n", dn, ctl->index);
+ doutc(cl, "dn %p idx %d\n", dn, ctl->index);
ctl->dentries[idx] = dn;
ctl->index++;
} else {
- dout("disable readdir cache\n");
+ doutc(cl, "disable readdir cache\n");
ctl->index = -1;
}
return 0;
@@ -1867,6 +1893,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
struct inode *inode = d_inode(parent);
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_mds_reply_info_parsed *rinfo = &req->r_reply_info;
+ struct ceph_client *cl = session->s_mdsc->fsc->client;
struct qstr dname;
struct dentry *dn;
struct inode *in;
@@ -1894,19 +1921,18 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
if (rinfo->dir_dir &&
le32_to_cpu(rinfo->dir_dir->frag) != frag) {
- dout("readdir_prepopulate got new frag %x -> %x\n",
- frag, le32_to_cpu(rinfo->dir_dir->frag));
+ doutc(cl, "got new frag %x -> %x\n", frag,
+ le32_to_cpu(rinfo->dir_dir->frag));
frag = le32_to_cpu(rinfo->dir_dir->frag);
if (!rinfo->hash_order)
req->r_readdir_offset = 2;
}
if (le32_to_cpu(rinfo->head->op) == CEPH_MDS_OP_LSSNAP) {
- dout("readdir_prepopulate %d items under SNAPDIR dn %p\n",
- rinfo->dir_nr, parent);
+ doutc(cl, "%d items under SNAPDIR dn %p\n",
+ rinfo->dir_nr, parent);
} else {
- dout("readdir_prepopulate %d items under dn %p\n",
- rinfo->dir_nr, parent);
+ doutc(cl, "%d items under dn %p\n", rinfo->dir_nr, parent);
if (rinfo->dir_dir)
ceph_fill_dirfrag(d_inode(parent), rinfo->dir_dir);
@@ -1950,15 +1976,15 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
retry_lookup:
dn = d_lookup(parent, &dname);
- dout("d_lookup on parent=%p name=%.*s got %p\n",
- parent, dname.len, dname.name, dn);
+ doutc(cl, "d_lookup on parent=%p name=%.*s got %p\n",
+ parent, dname.len, dname.name, dn);
if (!dn) {
dn = d_alloc(parent, &dname);
- dout("d_alloc %p '%.*s' = %p\n", parent,
- dname.len, dname.name, dn);
+ doutc(cl, "d_alloc %p '%.*s' = %p\n", parent,
+ dname.len, dname.name, dn);
if (!dn) {
- dout("d_alloc badness\n");
+ doutc(cl, "d_alloc badness\n");
err = -ENOMEM;
goto out;
}
@@ -1971,8 +1997,8 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
(ceph_ino(d_inode(dn)) != tvino.ino ||
ceph_snap(d_inode(dn)) != tvino.snap)) {
struct ceph_dentry_info *di = ceph_dentry(dn);
- dout(" dn %p points to wrong inode %p\n",
- dn, d_inode(dn));
+ doutc(cl, " dn %p points to wrong inode %p\n",
+ dn, d_inode(dn));
spin_lock(&dn->d_lock);
if (di->offset > 0 &&
@@ -1994,7 +2020,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
} else {
in = ceph_get_inode(parent->d_sb, tvino, NULL);
if (IS_ERR(in)) {
- dout("new_inode badness\n");
+ doutc(cl, "new_inode badness\n");
d_drop(dn);
dput(dn);
err = PTR_ERR(in);
@@ -2005,7 +2031,8 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
ret = ceph_fill_inode(in, NULL, &rde->inode, NULL, session,
-1, &req->r_caps_reservation);
if (ret < 0) {
- pr_err("ceph_fill_inode badness on %p\n", in);
+ pr_err_client(cl, "badness on %p %llx.%llx\n", in,
+ ceph_vinop(in));
if (d_really_is_negative(dn)) {
if (in->i_state & I_NEW) {
ihold(in);
@@ -2022,8 +2049,8 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
if (d_really_is_negative(dn)) {
if (ceph_security_xattr_deadlock(in)) {
- dout(" skip splicing dn %p to inode %p"
- " (security xattr deadlock)\n", dn, in);
+ doutc(cl, " skip splicing dn %p to inode %p"
+ " (security xattr deadlock)\n", dn, in);
iput(in);
skipped++;
goto next_item;
@@ -2055,17 +2082,18 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
req->r_readdir_cache_idx = cache_ctl.index;
}
ceph_readdir_cache_release(&cache_ctl);
- dout("readdir_prepopulate done\n");
+ doutc(cl, "done\n");
return err;
}
bool ceph_inode_set_size(struct inode *inode, loff_t size)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
bool ret;
spin_lock(&ci->i_ceph_lock);
- dout("set_size %p %llu -> %llu\n", inode, i_size_read(inode), size);
+ doutc(cl, "set_size %p %llu -> %llu\n", inode, i_size_read(inode), size);
i_size_write(inode, size);
ceph_fscache_update(inode);
inode->i_blocks = calc_inode_blocks(size);
@@ -2080,21 +2108,24 @@ bool ceph_inode_set_size(struct inode *inode, loff_t size)
void ceph_queue_inode_work(struct inode *inode, int work_bit)
{
struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
+ struct ceph_client *cl = fsc->client;
struct ceph_inode_info *ci = ceph_inode(inode);
set_bit(work_bit, &ci->i_work_mask);
ihold(inode);
if (queue_work(fsc->inode_wq, &ci->i_work)) {
- dout("queue_inode_work %p, mask=%lx\n", inode, ci->i_work_mask);
+ doutc(cl, "%p %llx.%llx mask=%lx\n", inode,
+ ceph_vinop(inode), ci->i_work_mask);
} else {
- dout("queue_inode_work %p already queued, mask=%lx\n",
- inode, ci->i_work_mask);
+ doutc(cl, "%p %llx.%llx already queued, mask=%lx\n",
+ inode, ceph_vinop(inode), ci->i_work_mask);
iput(inode);
}
}
static void ceph_do_invalidate_pages(struct inode *inode)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
u32 orig_gen;
int check = 0;
@@ -2104,8 +2135,9 @@ static void ceph_do_invalidate_pages(struct inode *inode)
mutex_lock(&ci->i_truncate_mutex);
if (ceph_inode_is_shutdown(inode)) {
- pr_warn_ratelimited("%s: inode %llx.%llx is shut down\n",
- __func__, ceph_vinop(inode));
+ pr_warn_ratelimited_client(cl,
+ "%p %llx.%llx is shut down\n", inode,
+ ceph_vinop(inode));
mapping_set_error(inode->i_mapping, -EIO);
truncate_pagecache(inode, 0);
mutex_unlock(&ci->i_truncate_mutex);
@@ -2113,8 +2145,8 @@ static void ceph_do_invalidate_pages(struct inode *inode)
}
spin_lock(&ci->i_ceph_lock);
- dout("invalidate_pages %p gen %d revoking %d\n", inode,
- ci->i_rdcache_gen, ci->i_rdcache_revoking);
+ doutc(cl, "%p %llx.%llx gen %d revoking %d\n", inode,
+ ceph_vinop(inode), ci->i_rdcache_gen, ci->i_rdcache_revoking);
if (ci->i_rdcache_revoking != ci->i_rdcache_gen) {
if (__ceph_caps_revoking_other(ci, NULL, CEPH_CAP_FILE_CACHE))
check = 1;
@@ -2126,21 +2158,21 @@ static void ceph_do_invalidate_pages(struct inode *inode)
spin_unlock(&ci->i_ceph_lock);
if (invalidate_inode_pages2(inode->i_mapping) < 0) {
- pr_err("invalidate_inode_pages2 %llx.%llx failed\n",
- ceph_vinop(inode));
+ pr_err_client(cl, "invalidate_inode_pages2 %llx.%llx failed\n",
+ ceph_vinop(inode));
}
spin_lock(&ci->i_ceph_lock);
if (orig_gen == ci->i_rdcache_gen &&
orig_gen == ci->i_rdcache_revoking) {
- dout("invalidate_pages %p gen %d successful\n", inode,
- ci->i_rdcache_gen);
+ doutc(cl, "%p %llx.%llx gen %d successful\n", inode,
+ ceph_vinop(inode), ci->i_rdcache_gen);
ci->i_rdcache_revoking--;
check = 1;
} else {
- dout("invalidate_pages %p gen %d raced, now %d revoking %d\n",
- inode, orig_gen, ci->i_rdcache_gen,
- ci->i_rdcache_revoking);
+ doutc(cl, "%p %llx.%llx gen %d raced, now %d revoking %d\n",
+ inode, ceph_vinop(inode), orig_gen, ci->i_rdcache_gen,
+ ci->i_rdcache_revoking);
if (__ceph_caps_revoking_other(ci, NULL, CEPH_CAP_FILE_CACHE))
check = 1;
}
@@ -2157,6 +2189,7 @@ static void ceph_do_invalidate_pages(struct inode *inode)
*/
void __ceph_do_pending_vmtruncate(struct inode *inode)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
u64 to;
int wrbuffer_refs, finish = 0;
@@ -2165,7 +2198,8 @@ void __ceph_do_pending_vmtruncate(struct inode *inode)
retry:
spin_lock(&ci->i_ceph_lock);
if (ci->i_truncate_pending == 0) {
- dout("%s %p none pending\n", __func__, inode);
+ doutc(cl, "%p %llx.%llx none pending\n", inode,
+ ceph_vinop(inode));
spin_unlock(&ci->i_ceph_lock);
mutex_unlock(&ci->i_truncate_mutex);
return;
@@ -2177,7 +2211,8 @@ void __ceph_do_pending_vmtruncate(struct inode *inode)
*/
if (ci->i_wrbuffer_ref_head < ci->i_wrbuffer_ref) {
spin_unlock(&ci->i_ceph_lock);
- dout("%s %p flushing snaps first\n", __func__, inode);
+ doutc(cl, "%p %llx.%llx flushing snaps first\n", inode,
+ ceph_vinop(inode));
filemap_write_and_wait_range(&inode->i_data, 0,
inode->i_sb->s_maxbytes);
goto retry;
@@ -2188,8 +2223,8 @@ void __ceph_do_pending_vmtruncate(struct inode *inode)
to = ci->i_truncate_pagecache_size;
wrbuffer_refs = ci->i_wrbuffer_ref;
- dout("%s %p (%d) to %lld\n", __func__, inode,
- ci->i_truncate_pending, to);
+ doutc(cl, "%p %llx.%llx (%d) to %lld\n", inode, ceph_vinop(inode),
+ ci->i_truncate_pending, to);
spin_unlock(&ci->i_ceph_lock);
ceph_fscache_resize(inode, to);
@@ -2217,9 +2252,10 @@ static void ceph_inode_work(struct work_struct *work)
struct ceph_inode_info *ci = container_of(work, struct ceph_inode_info,
i_work);
struct inode *inode = &ci->netfs.inode;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
if (test_and_clear_bit(CEPH_I_WORK_WRITEBACK, &ci->i_work_mask)) {
- dout("writeback %p\n", inode);
+ doutc(cl, "writeback %p %llx.%llx\n", inode, ceph_vinop(inode));
filemap_fdatawrite(&inode->i_data);
}
if (test_and_clear_bit(CEPH_I_WORK_INVALIDATE_PAGES, &ci->i_work_mask))
@@ -2291,6 +2327,7 @@ static int fill_fscrypt_truncate(struct inode *inode,
struct ceph_mds_request *req,
struct iattr *attr)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
int boff = attr->ia_size % CEPH_FSCRYPT_BLOCK_SIZE;
loff_t pos, orig_pos = round_down(attr->ia_size,
@@ -2313,9 +2350,9 @@ static int fill_fscrypt_truncate(struct inode *inode,
issued = __ceph_caps_issued(ci, NULL);
- dout("%s size %lld -> %lld got cap refs on %s, issued %s\n", __func__,
- i_size, attr->ia_size, ceph_cap_string(got),
- ceph_cap_string(issued));
+ doutc(cl, "size %lld -> %lld got cap refs on %s, issued %s\n",
+ i_size, attr->ia_size, ceph_cap_string(got),
+ ceph_cap_string(issued));
/* Try to writeback the dirty pagecaches */
if (issued & (CEPH_CAP_FILE_BUFFER)) {
@@ -2370,8 +2407,7 @@ static int fill_fscrypt_truncate(struct inode *inode,
* If the Rados object doesn't exist, it will be set to 0.
*/
if (!objver) {
- dout("%s hit hole, ppos %lld < size %lld\n", __func__,
- pos, i_size);
+ doutc(cl, "hit hole, ppos %lld < size %lld\n", pos, i_size);
header.data_len = cpu_to_le32(8 + 8 + 4);
header.file_offset = 0;
@@ -2380,8 +2416,8 @@ static int fill_fscrypt_truncate(struct inode *inode,
header.data_len = cpu_to_le32(8 + 8 + 4 + CEPH_FSCRYPT_BLOCK_SIZE);
header.file_offset = cpu_to_le64(orig_pos);
- dout("%s encrypt block boff/bsize %d/%lu\n", __func__,
- boff, CEPH_FSCRYPT_BLOCK_SIZE);
+ doutc(cl, "encrypt block boff/bsize %d/%lu\n", boff,
+ CEPH_FSCRYPT_BLOCK_SIZE);
/* truncate and zero out the extra contents for the last block */
memset(iov.iov_base + boff, 0, PAGE_SIZE - boff);
@@ -2409,8 +2445,8 @@ static int fill_fscrypt_truncate(struct inode *inode,
}
req->r_pagelist = pagelist;
out:
- dout("%s %p size dropping cap refs on %s\n", __func__,
- inode, ceph_cap_string(got));
+ doutc(cl, "%p %llx.%llx size dropping cap refs on %s\n", inode,
+ ceph_vinop(inode), ceph_cap_string(got));
ceph_put_cap_refs(ci, got);
if (iov.iov_base)
kunmap_local(iov.iov_base);
@@ -2428,6 +2464,7 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr,
unsigned int ia_valid = attr->ia_valid;
struct ceph_mds_request *req;
struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_cap_flush *prealloc_cf;
loff_t isize = i_size_read(inode);
int issued;
@@ -2466,7 +2503,8 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr,
}
}
- dout("setattr %p issued %s\n", inode, ceph_cap_string(issued));
+ doutc(cl, "%p %llx.%llx issued %s\n", inode, ceph_vinop(inode),
+ ceph_cap_string(issued));
#if IS_ENABLED(CONFIG_FS_ENCRYPTION)
if (cia && cia->fscrypt_auth) {
u32 len = ceph_fscrypt_auth_len(cia->fscrypt_auth);
@@ -2477,8 +2515,8 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr,
goto out;
}
- dout("setattr %llx:%llx fscrypt_auth len %u to %u)\n",
- ceph_vinop(inode), ci->fscrypt_auth_len, len);
+ doutc(cl, "%p %llx.%llx fscrypt_auth len %u to %u)\n", inode,
+ ceph_vinop(inode), ci->fscrypt_auth_len, len);
/* It should never be re-set once set */
WARN_ON_ONCE(ci->fscrypt_auth);
@@ -2506,9 +2544,10 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr,
#endif /* CONFIG_FS_ENCRYPTION */
if (ia_valid & ATTR_UID) {
- dout("setattr %p uid %d -> %d\n", inode,
- from_kuid(&init_user_ns, inode->i_uid),
- from_kuid(&init_user_ns, attr->ia_uid));
+ doutc(cl, "%p %llx.%llx uid %d -> %d\n", inode,
+ ceph_vinop(inode),
+ from_kuid(&init_user_ns, inode->i_uid),
+ from_kuid(&init_user_ns, attr->ia_uid));
if (issued & CEPH_CAP_AUTH_EXCL) {
inode->i_uid = attr->ia_uid;
dirtied |= CEPH_CAP_AUTH_EXCL;
@@ -2521,9 +2560,10 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr,
}
}
if (ia_valid & ATTR_GID) {
- dout("setattr %p gid %d -> %d\n", inode,
- from_kgid(&init_user_ns, inode->i_gid),
- from_kgid(&init_user_ns, attr->ia_gid));
+ doutc(cl, "%p %llx.%llx gid %d -> %d\n", inode,
+ ceph_vinop(inode),
+ from_kgid(&init_user_ns, inode->i_gid),
+ from_kgid(&init_user_ns, attr->ia_gid));
if (issued & CEPH_CAP_AUTH_EXCL) {
inode->i_gid = attr->ia_gid;
dirtied |= CEPH_CAP_AUTH_EXCL;
@@ -2536,8 +2576,8 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr,
}
}
if (ia_valid & ATTR_MODE) {
- dout("setattr %p mode 0%o -> 0%o\n", inode, inode->i_mode,
- attr->ia_mode);
+ doutc(cl, "%p %llx.%llx mode 0%o -> 0%o\n", inode,
+ ceph_vinop(inode), inode->i_mode, attr->ia_mode);
if (issued & CEPH_CAP_AUTH_EXCL) {
inode->i_mode = attr->ia_mode;
dirtied |= CEPH_CAP_AUTH_EXCL;
@@ -2551,9 +2591,10 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr,
}
if (ia_valid & ATTR_ATIME) {
- dout("setattr %p atime %lld.%ld -> %lld.%ld\n", inode,
- inode->i_atime.tv_sec, inode->i_atime.tv_nsec,
- attr->ia_atime.tv_sec, attr->ia_atime.tv_nsec);
+ doutc(cl, "%p %llx.%llx atime %lld.%ld -> %lld.%ld\n",
+ inode, ceph_vinop(inode), inode->i_atime.tv_sec,
+ inode->i_atime.tv_nsec, attr->ia_atime.tv_sec,
+ attr->ia_atime.tv_nsec);
if (issued & CEPH_CAP_FILE_EXCL) {
ci->i_time_warp_seq++;
inode->i_atime = attr->ia_atime;
@@ -2573,7 +2614,8 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr,
}
}
if (ia_valid & ATTR_SIZE) {
- dout("setattr %p size %lld -> %lld\n", inode, isize, attr->ia_size);
+ doutc(cl, "%p %llx.%llx size %lld -> %lld\n", inode,
+ ceph_vinop(inode), isize, attr->ia_size);
/*
* Only when the new size is smaller and not aligned to
* CEPH_FSCRYPT_BLOCK_SIZE will the RMW is needed.
@@ -2624,9 +2666,10 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr,
}
}
if (ia_valid & ATTR_MTIME) {
- dout("setattr %p mtime %lld.%ld -> %lld.%ld\n", inode,
- inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
- attr->ia_mtime.tv_sec, attr->ia_mtime.tv_nsec);
+ doutc(cl, "%p %llx.%llx mtime %lld.%ld -> %lld.%ld\n",
+ inode, ceph_vinop(inode), inode->i_mtime.tv_sec,
+ inode->i_mtime.tv_nsec, attr->ia_mtime.tv_sec,
+ attr->ia_mtime.tv_nsec);
if (issued & CEPH_CAP_FILE_EXCL) {
ci->i_time_warp_seq++;
inode->i_mtime = attr->ia_mtime;
@@ -2650,11 +2693,12 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr,
if (ia_valid & ATTR_CTIME) {
bool only = (ia_valid & (ATTR_SIZE|ATTR_MTIME|ATTR_ATIME|
ATTR_MODE|ATTR_UID|ATTR_GID)) == 0;
- dout("setattr %p ctime %lld.%ld -> %lld.%ld (%s)\n", inode,
- inode_get_ctime(inode).tv_sec,
- inode_get_ctime(inode).tv_nsec,
- attr->ia_ctime.tv_sec, attr->ia_ctime.tv_nsec,
- only ? "ctime only" : "ignored");
+ doutc(cl, "%p %llx.%llx ctime %lld.%ld -> %lld.%ld (%s)\n",
+ inode, ceph_vinop(inode), inode_get_ctime(inode).tv_sec,
+ inode_get_ctime(inode).tv_nsec,
+ attr->ia_ctime.tv_sec, attr->ia_ctime.tv_nsec,
+ only ? "ctime only" : "ignored");
+
if (only) {
/*
* if kernel wants to dirty ctime but nothing else,
@@ -2672,7 +2716,8 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr,
}
}
if (ia_valid & ATTR_FILE)
- dout("setattr %p ATTR_FILE ... hrm!\n", inode);
+ doutc(cl, "%p %llx.%llx ATTR_FILE ... hrm!\n", inode,
+ ceph_vinop(inode));
if (dirtied) {
inode_dirty_flags = __ceph_mark_dirty_caps(ci, dirtied,
@@ -2713,16 +2758,17 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr,
*/
err = ceph_mdsc_do_request(mdsc, NULL, req);
if (err == -EAGAIN && truncate_retry--) {
- dout("setattr %p result=%d (%s locally, %d remote), retry it!\n",
- inode, err, ceph_cap_string(dirtied), mask);
+ doutc(cl, "%p %llx.%llx result=%d (%s locally, %d remote), retry it!\n",
+ inode, ceph_vinop(inode), err,
+ ceph_cap_string(dirtied), mask);
ceph_mdsc_put_request(req);
ceph_free_cap_flush(prealloc_cf);
goto retry;
}
}
out:
- dout("setattr %p result=%d (%s locally, %d remote)\n", inode, err,
- ceph_cap_string(dirtied), mask);
+ doutc(cl, "%p %llx.%llx result=%d (%s locally, %d remote)\n", inode,
+ ceph_vinop(inode), err, ceph_cap_string(dirtied), mask);
ceph_mdsc_put_request(req);
ceph_free_cap_flush(prealloc_cf);
@@ -2811,18 +2857,20 @@ int __ceph_do_getattr(struct inode *inode, struct page *locked_page,
int mask, bool force)
{
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(inode->i_sb);
+ struct ceph_client *cl = fsc->client;
struct ceph_mds_client *mdsc = fsc->mdsc;
struct ceph_mds_request *req;
int mode;
int err;
if (ceph_snap(inode) == CEPH_SNAPDIR) {
- dout("do_getattr inode %p SNAPDIR\n", inode);
+ doutc(cl, "inode %p %llx.%llx SNAPDIR\n", inode,
+ ceph_vinop(inode));
return 0;
}
- dout("do_getattr inode %p mask %s mode 0%o\n",
- inode, ceph_cap_string(mask), inode->i_mode);
+ doutc(cl, "inode %p %llx.%llx mask %s mode 0%o\n", inode,
+ ceph_vinop(inode), ceph_cap_string(mask), inode->i_mode);
if (!force && ceph_caps_issued_mask_metric(ceph_inode(inode), mask, 1))
return 0;
@@ -2849,7 +2897,7 @@ int __ceph_do_getattr(struct inode *inode, struct page *locked_page,
}
}
ceph_mdsc_put_request(req);
- dout("do_getattr result=%d\n", err);
+ doutc(cl, "result=%d\n", err);
return err;
}
@@ -2857,6 +2905,7 @@ int ceph_do_getvxattr(struct inode *inode, const char *name, void *value,
size_t size)
{
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(inode->i_sb);
+ struct ceph_client *cl = fsc->client;
struct ceph_mds_client *mdsc = fsc->mdsc;
struct ceph_mds_request *req;
int mode = USE_AUTH_MDS;
@@ -2886,7 +2935,7 @@ int ceph_do_getvxattr(struct inode *inode, const char *name, void *value,
xattr_value = req->r_reply_info.xattr_info.xattr_value;
xattr_value_len = req->r_reply_info.xattr_info.xattr_value_len;
- dout("do_getvxattr xattr_value_len:%zu, size:%zu\n", xattr_value_len, size);
+ doutc(cl, "xattr_value_len:%zu, size:%zu\n", xattr_value_len, size);
err = (int)xattr_value_len;
if (size == 0)
@@ -2901,7 +2950,7 @@ int ceph_do_getvxattr(struct inode *inode, const char *name, void *value,
put:
ceph_mdsc_put_request(req);
out:
- dout("do_getvxattr result=%d\n", err);
+ doutc(cl, "result=%d\n", err);
return err;
}
diff --git a/fs/ceph/ioctl.c b/fs/ceph/ioctl.c
index 3f617146e4ad..e861de3c79b9 100644
--- a/fs/ceph/ioctl.c
+++ b/fs/ceph/ioctl.c
@@ -245,6 +245,7 @@ static long ceph_ioctl_lazyio(struct file *file)
struct inode *inode = file_inode(file);
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc;
+ struct ceph_client *cl = mdsc->fsc->client;
if ((fi->fmode & CEPH_FILE_MODE_LAZY) == 0) {
spin_lock(&ci->i_ceph_lock);
@@ -252,11 +253,13 @@ static long ceph_ioctl_lazyio(struct file *file)
ci->i_nr_by_mode[ffs(CEPH_FILE_MODE_LAZY)]++;
__ceph_touch_fmode(ci, mdsc, fi->fmode);
spin_unlock(&ci->i_ceph_lock);
- dout("ioctl_layzio: file %p marked lazy\n", file);
+ doutc(cl, "file %p %p %llx.%llx marked lazy\n", file, inode,
+ ceph_vinop(inode));
ceph_check_caps(ci, 0);
} else {
- dout("ioctl_layzio: file %p already lazy\n", file);
+ doutc(cl, "file %p %p %llx.%llx already lazy\n", file, inode,
+ ceph_vinop(inode));
}
return 0;
}
@@ -355,10 +358,12 @@ static const char *ceph_ioctl_cmd_name(const unsigned int cmd)
long ceph_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
+ struct inode *inode = file_inode(file);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
int ret;
- dout("ioctl file %p cmd %s arg %lu\n", file,
- ceph_ioctl_cmd_name(cmd), arg);
+ doutc(fsc->client, "file %p %p %llx.%llx cmd %s arg %lu\n", file,
+ inode, ceph_vinop(inode), ceph_ioctl_cmd_name(cmd), arg);
switch (cmd) {
case CEPH_IOC_GET_LAYOUT:
return ceph_ioctl_get_layout(file, (void __user *)arg);
diff --git a/fs/ceph/locks.c b/fs/ceph/locks.c
index 02f5fbe83aa4..45ba83f202b8 100644
--- a/fs/ceph/locks.c
+++ b/fs/ceph/locks.c
@@ -77,6 +77,7 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct inode *inode,
int cmd, u8 wait, struct file_lock *fl)
{
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mds_request *req;
int err;
u64 length = 0;
@@ -111,10 +112,10 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct inode *inode,
owner = secure_addr(fl->fl_owner);
- dout("ceph_lock_message: rule: %d, op: %d, owner: %llx, pid: %llu, "
- "start: %llu, length: %llu, wait: %d, type: %d\n", (int)lock_type,
- (int)operation, owner, (u64)fl->fl_pid, fl->fl_start, length,
- wait, fl->fl_type);
+ doutc(cl, "rule: %d, op: %d, owner: %llx, pid: %llu, "
+ "start: %llu, length: %llu, wait: %d, type: %d\n",
+ (int)lock_type, (int)operation, owner, (u64)fl->fl_pid,
+ fl->fl_start, length, wait, fl->fl_type);
req->r_args.filelock_change.rule = lock_type;
req->r_args.filelock_change.type = cmd;
@@ -147,16 +148,17 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct inode *inode,
}
ceph_mdsc_put_request(req);
- dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, "
- "length: %llu, wait: %d, type: %d, err code %d\n", (int)lock_type,
- (int)operation, (u64)fl->fl_pid, fl->fl_start,
- length, wait, fl->fl_type, err);
+ doutc(cl, "rule: %d, op: %d, pid: %llu, start: %llu, "
+ "length: %llu, wait: %d, type: %d, err code %d\n",
+ (int)lock_type, (int)operation, (u64)fl->fl_pid,
+ fl->fl_start, length, wait, fl->fl_type, err);
return err;
}
static int ceph_lock_wait_for_completion(struct ceph_mds_client *mdsc,
struct ceph_mds_request *req)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mds_request *intr_req;
struct inode *inode = req->r_inode;
int err, lock_type;
@@ -174,8 +176,7 @@ static int ceph_lock_wait_for_completion(struct ceph_mds_client *mdsc,
if (!err)
return 0;
- dout("ceph_lock_wait_for_completion: request %llu was interrupted\n",
- req->r_tid);
+ doutc(cl, "request %llu was interrupted\n", req->r_tid);
mutex_lock(&mdsc->mutex);
if (test_bit(CEPH_MDS_R_GOT_RESULT, &req->r_req_flags)) {
@@ -249,6 +250,7 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
{
struct inode *inode = file_inode(file);
struct ceph_inode_info *ci = ceph_inode(inode);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
int err = 0;
u16 op = CEPH_MDS_OP_SETFILELOCK;
u8 wait = 0;
@@ -260,7 +262,7 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
if (ceph_inode_is_shutdown(inode))
return -ESTALE;
- dout("ceph_lock, fl_owner: %p\n", fl->fl_owner);
+ doutc(cl, "fl_owner: %p\n", fl->fl_owner);
/* set wait bit as appropriate, then make command as Ceph expects it*/
if (IS_GETLK(cmd))
@@ -295,7 +297,7 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
err = ceph_lock_message(CEPH_LOCK_FCNTL, op, inode, lock_cmd, wait, fl);
if (!err) {
if (op == CEPH_MDS_OP_SETFILELOCK && F_UNLCK != fl->fl_type) {
- dout("mds locked, locking locally\n");
+ doutc(cl, "locking locally\n");
err = posix_lock_file(file, fl, NULL);
if (err) {
/* undo! This should only happen if
@@ -303,8 +305,8 @@ int ceph_lock(struct file *file, int cmd, struct file_lock *fl)
* deadlock. */
ceph_lock_message(CEPH_LOCK_FCNTL, op, inode,
CEPH_LOCK_UNLOCK, 0, fl);
- dout("got %d on posix_lock_file, undid lock\n",
- err);
+ doutc(cl, "got %d on posix_lock_file, undid lock\n",
+ err);
}
}
}
@@ -315,6 +317,7 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
{
struct inode *inode = file_inode(file);
struct ceph_inode_info *ci = ceph_inode(inode);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
int err = 0;
u8 wait = 0;
u8 lock_cmd;
@@ -325,7 +328,7 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
if (ceph_inode_is_shutdown(inode))
return -ESTALE;
- dout("ceph_flock, fl_file: %p\n", fl->fl_file);
+ doutc(cl, "fl_file: %p\n", fl->fl_file);
spin_lock(&ci->i_ceph_lock);
if (ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK) {
@@ -362,7 +365,8 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
ceph_lock_message(CEPH_LOCK_FLOCK,
CEPH_MDS_OP_SETFILELOCK,
inode, CEPH_LOCK_UNLOCK, 0, fl);
- dout("got %d on locks_lock_file_wait, undid lock\n", err);
+ doutc(cl, "got %d on locks_lock_file_wait, undid lock\n",
+ err);
}
}
return err;
@@ -374,6 +378,7 @@ int ceph_flock(struct file *file, int cmd, struct file_lock *fl)
*/
void ceph_count_locks(struct inode *inode, int *fcntl_count, int *flock_count)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct file_lock *lock;
struct file_lock_context *ctx;
@@ -389,17 +394,20 @@ void ceph_count_locks(struct inode *inode, int *fcntl_count, int *flock_count)
++(*flock_count);
spin_unlock(&ctx->flc_lock);
}
- dout("counted %d flock locks and %d fcntl locks\n",
- *flock_count, *fcntl_count);
+ doutc(cl, "counted %d flock locks and %d fcntl locks\n",
+ *flock_count, *fcntl_count);
}
/*
* Given a pointer to a lock, convert it to a ceph filelock
*/
-static int lock_to_ceph_filelock(struct file_lock *lock,
+static int lock_to_ceph_filelock(struct inode *inode,
+ struct file_lock *lock,
struct ceph_filelock *cephlock)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
int err = 0;
+
cephlock->start = cpu_to_le64(lock->fl_start);
cephlock->length = cpu_to_le64(lock->fl_end - lock->fl_start + 1);
cephlock->client = cpu_to_le64(0);
@@ -417,7 +425,7 @@ static int lock_to_ceph_filelock(struct file_lock *lock,
cephlock->type = CEPH_LOCK_UNLOCK;
break;
default:
- dout("Have unknown lock type %d\n", lock->fl_type);
+ doutc(cl, "Have unknown lock type %d\n", lock->fl_type);
err = -EINVAL;
}
@@ -435,13 +443,14 @@ int ceph_encode_locks_to_buffer(struct inode *inode,
{
struct file_lock *lock;
struct file_lock_context *ctx = locks_inode_context(inode);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
int err = 0;
int seen_fcntl = 0;
int seen_flock = 0;
int l = 0;
- dout("encoding %d flock and %d fcntl locks\n", num_flock_locks,
- num_fcntl_locks);
+ doutc(cl, "encoding %d flock and %d fcntl locks\n", num_flock_locks,
+ num_fcntl_locks);
if (!ctx)
return 0;
@@ -453,7 +462,7 @@ int ceph_encode_locks_to_buffer(struct inode *inode,
err = -ENOSPC;
goto fail;
}
- err = lock_to_ceph_filelock(lock, &flocks[l]);
+ err = lock_to_ceph_filelock(inode, lock, &flocks[l]);
if (err)
goto fail;
++l;
@@ -464,7 +473,7 @@ int ceph_encode_locks_to_buffer(struct inode *inode,
err = -ENOSPC;
goto fail;
}
- err = lock_to_ceph_filelock(lock, &flocks[l]);
+ err = lock_to_ceph_filelock(inode, lock, &flocks[l]);
if (err)
goto fail;
++l;
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 50d5cb85332b..a83aca62ded9 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -411,6 +411,7 @@ static int parse_reply_info_readdir(void **p, void *end,
u64 features)
{
struct ceph_mds_reply_info_parsed *info = &req->r_reply_info;
+ struct ceph_client *cl = req->r_mdsc->fsc->client;
u32 num, i = 0;
int err;
@@ -433,7 +434,7 @@ static int parse_reply_info_readdir(void **p, void *end,
BUG_ON(!info->dir_entries);
if ((unsigned long)(info->dir_entries + num) >
(unsigned long)info->dir_entries + info->dir_buf_size) {
- pr_err("dir contents are larger than expected\n");
+ pr_err_client(cl, "dir contents are larger than expected\n");
WARN_ON(1);
goto bad;
}
@@ -454,7 +455,7 @@ static int parse_reply_info_readdir(void **p, void *end,
ceph_decode_need(p, end, _name_len, bad);
_name = *p;
*p += _name_len;
- dout("parsed dir dname '%.*s'\n", _name_len, _name);
+ doutc(cl, "parsed dir dname '%.*s'\n", _name_len, _name);
if (info->hash_order)
rde->raw_hash = ceph_str_hash(ci->i_dir_layout.dl_dir_hash,
@@ -514,8 +515,8 @@ static int parse_reply_info_readdir(void **p, void *end,
rde->is_nokey = false;
err = ceph_fname_to_usr(&fname, &tname, &oname, &rde->is_nokey);
if (err) {
- pr_err("%s unable to decode %.*s, got %d\n", __func__,
- _name_len, _name, err);
+ pr_err_client(cl, "unable to decode %.*s, got %d\n",
+ _name_len, _name, err);
goto out_bad;
}
rde->name = oname.name;
@@ -539,7 +540,7 @@ static int parse_reply_info_readdir(void **p, void *end,
bad:
err = -EIO;
out_bad:
- pr_err("problem parsing dir contents %d\n", err);
+ pr_err_client(cl, "problem parsing dir contents %d\n", err);
return err;
}
@@ -570,10 +571,11 @@ static int parse_reply_info_filelock(void **p, void *end,
static int ceph_parse_deleg_inos(void **p, void *end,
struct ceph_mds_session *s)
{
+ struct ceph_client *cl = s->s_mdsc->fsc->client;
u32 sets;
ceph_decode_32_safe(p, end, sets, bad);
- dout("got %u sets of delegated inodes\n", sets);
+ doutc(cl, "got %u sets of delegated inodes\n", sets);
while (sets--) {
u64 start, len;
@@ -582,8 +584,9 @@ static int ceph_parse_deleg_inos(void **p, void *end,
/* Don't accept a delegation of system inodes */
if (start < CEPH_INO_SYSTEM_BASE) {
- pr_warn_ratelimited("ceph: ignoring reserved inode range delegation (start=0x%llx len=0x%llx)\n",
- start, len);
+ pr_warn_ratelimited_client(cl,
+ "ignoring reserved inode range delegation (start=0x%llx len=0x%llx)\n",
+ start, len);
continue;
}
while (len--) {
@@ -591,10 +594,10 @@ static int ceph_parse_deleg_inos(void **p, void *end,
DELEGATED_INO_AVAILABLE,
GFP_KERNEL);
if (!err) {
- dout("added delegated inode 0x%llx\n",
- start - 1);
+ doutc(cl, "added delegated inode 0x%llx\n", start - 1);
} else if (err == -EBUSY) {
- pr_warn("MDS delegated inode 0x%llx more than once.\n",
+ pr_warn_client(cl,
+ "MDS delegated inode 0x%llx more than once.\n",
start - 1);
} else {
return err;
@@ -744,6 +747,7 @@ static int parse_reply_info(struct ceph_mds_session *s, struct ceph_msg *msg,
struct ceph_mds_request *req, u64 features)
{
struct ceph_mds_reply_info_parsed *info = &req->r_reply_info;
+ struct ceph_client *cl = s->s_mdsc->fsc->client;
void *p, *end;
u32 len;
int err;
@@ -783,7 +787,7 @@ static int parse_reply_info(struct ceph_mds_session *s, struct ceph_msg *msg,
bad:
err = -EIO;
out_bad:
- pr_err("mds parse_reply err %d\n", err);
+ pr_err_client(cl, "mds parse_reply err %d\n", err);
ceph_msg_dump(msg);
return err;
}
@@ -831,6 +835,7 @@ static void destroy_reply_info(struct ceph_mds_reply_info_parsed *info)
int ceph_wait_on_conflict_unlink(struct dentry *dentry)
{
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dentry->d_sb);
+ struct ceph_client *cl = fsc->client;
struct dentry *pdentry = dentry->d_parent;
struct dentry *udentry, *found = NULL;
struct ceph_dentry_info *di;
@@ -855,8 +860,8 @@ int ceph_wait_on_conflict_unlink(struct dentry *dentry)
goto next;
if (!test_bit(CEPH_DENTRY_ASYNC_UNLINK_BIT, &di->flags))
- pr_warn("%s dentry %p:%pd async unlink bit is not set\n",
- __func__, dentry, dentry);
+ pr_warn_client(cl, "dentry %p:%pd async unlink bit is not set\n",
+ dentry, dentry);
if (!d_same_name(udentry, pdentry, &dname))
goto next;
@@ -872,8 +877,8 @@ int ceph_wait_on_conflict_unlink(struct dentry *dentry)
if (likely(!found))
return 0;
- dout("%s dentry %p:%pd conflict with old %p:%pd\n", __func__,
- dentry, dentry, found, found);
+ doutc(cl, "dentry %p:%pd conflict with old %p:%pd\n", dentry, dentry,
+ found, found);
err = wait_on_bit(&di->flags, CEPH_DENTRY_ASYNC_UNLINK_BIT,
TASK_KILLABLE);
@@ -957,6 +962,7 @@ static int __verify_registered_session(struct ceph_mds_client *mdsc,
static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
int mds)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mds_session *s;
if (READ_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_FENCE_IO)
@@ -973,7 +979,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
int newmax = 1 << get_count_order(mds + 1);
struct ceph_mds_session **sa;
- dout("%s: realloc to %d\n", __func__, newmax);
+ doutc(cl, "realloc to %d\n", newmax);
sa = kcalloc(newmax, sizeof(void *), GFP_NOFS);
if (!sa)
goto fail_realloc;
@@ -986,7 +992,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
mdsc->max_sessions = newmax;
}
- dout("%s: mds%d\n", __func__, mds);
+ doutc(cl, "mds%d\n", mds);
s->s_mdsc = mdsc;
s->s_mds = mds;
s->s_state = CEPH_MDS_SESSION_NEW;
@@ -1029,7 +1035,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
static void __unregister_session(struct ceph_mds_client *mdsc,
struct ceph_mds_session *s)
{
- dout("__unregister_session mds%d %p\n", s->s_mds, s);
+ doutc(mdsc->fsc->client, "mds%d %p\n", s->s_mds, s);
BUG_ON(mdsc->sessions[s->s_mds] != s);
mdsc->sessions[s->s_mds] = NULL;
ceph_con_close(&s->s_con);
@@ -1155,6 +1161,7 @@ static void __register_request(struct ceph_mds_client *mdsc,
struct ceph_mds_request *req,
struct inode *dir)
{
+ struct ceph_client *cl = mdsc->fsc->client;
int ret = 0;
req->r_tid = ++mdsc->last_tid;
@@ -1162,14 +1169,14 @@ static void __register_request(struct ceph_mds_client *mdsc,
ret = ceph_reserve_caps(mdsc, &req->r_caps_reservation,
req->r_num_caps);
if (ret < 0) {
- pr_err("__register_request %p "
- "failed to reserve caps: %d\n", req, ret);
+ pr_err_client(cl, "%p failed to reserve caps: %d\n",
+ req, ret);
/* set req->r_err to fail early from __do_request */
req->r_err = ret;
return;
}
}
- dout("__register_request %p tid %lld\n", req, req->r_tid);
+ doutc(cl, "%p tid %lld\n", req, req->r_tid);
ceph_mdsc_get_request(req);
insert_request(&mdsc->request_tree, req);
@@ -1192,7 +1199,7 @@ static void __register_request(struct ceph_mds_client *mdsc,
static void __unregister_request(struct ceph_mds_client *mdsc,
struct ceph_mds_request *req)
{
- dout("__unregister_request %p tid %lld\n", req, req->r_tid);
+ doutc(mdsc->fsc->client, "%p tid %lld\n", req, req->r_tid);
/* Never leave an unregistered request on an unsafe list! */
list_del_init(&req->r_unsafe_item);
@@ -1278,6 +1285,7 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
int mds = -1;
u32 hash = req->r_direct_hash;
bool is_hash = test_bit(CEPH_MDS_R_DIRECT_IS_HASH, &req->r_req_flags);
+ struct ceph_client *cl = mdsc->fsc->client;
if (random)
*random = false;
@@ -1289,8 +1297,7 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
if (req->r_resend_mds >= 0 &&
(__have_session(mdsc, req->r_resend_mds) ||
ceph_mdsmap_get_state(mdsc->mdsmap, req->r_resend_mds) > 0)) {
- dout("%s using resend_mds mds%d\n", __func__,
- req->r_resend_mds);
+ doutc(cl, "using resend_mds mds%d\n", req->r_resend_mds);
return req->r_resend_mds;
}
@@ -1307,7 +1314,8 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
rcu_read_lock();
inode = get_nonsnap_parent(req->r_dentry);
rcu_read_unlock();
- dout("%s using snapdir's parent %p\n", __func__, inode);
+ doutc(cl, "using snapdir's parent %p %llx.%llx\n",
+ inode, ceph_vinop(inode));
}
} else if (req->r_dentry) {
/* ignore race with rename; old or new d_parent is okay */
@@ -1327,7 +1335,8 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
/* direct snapped/virtual snapdir requests
* based on parent dir inode */
inode = get_nonsnap_parent(parent);
- dout("%s using nonsnap parent %p\n", __func__, inode);
+ doutc(cl, "using nonsnap parent %p %llx.%llx\n",
+ inode, ceph_vinop(inode));
} else {
/* dentry target */
inode = d_inode(req->r_dentry);
@@ -1343,10 +1352,11 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
rcu_read_unlock();
}
- dout("%s %p is_hash=%d (0x%x) mode %d\n", __func__, inode, (int)is_hash,
- hash, mode);
if (!inode)
goto random;
+
+ doutc(cl, "%p %llx.%llx is_hash=%d (0x%x) mode %d\n", inode,
+ ceph_vinop(inode), (int)is_hash, hash, mode);
ci = ceph_inode(inode);
if (is_hash && S_ISDIR(inode->i_mode)) {
@@ -1362,9 +1372,9 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
get_random_bytes(&r, 1);
r %= frag.ndist;
mds = frag.dist[r];
- dout("%s %p %llx.%llx frag %u mds%d (%d/%d)\n",
- __func__, inode, ceph_vinop(inode),
- frag.frag, mds, (int)r, frag.ndist);
+ doutc(cl, "%p %llx.%llx frag %u mds%d (%d/%d)\n",
+ inode, ceph_vinop(inode), frag.frag,
+ mds, (int)r, frag.ndist);
if (ceph_mdsmap_get_state(mdsc->mdsmap, mds) >=
CEPH_MDS_STATE_ACTIVE &&
!ceph_mdsmap_is_laggy(mdsc->mdsmap, mds))
@@ -1377,9 +1387,8 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
if (frag.mds >= 0) {
/* choose auth mds */
mds = frag.mds;
- dout("%s %p %llx.%llx frag %u mds%d (auth)\n",
- __func__, inode, ceph_vinop(inode),
- frag.frag, mds);
+ doutc(cl, "%p %llx.%llx frag %u mds%d (auth)\n",
+ inode, ceph_vinop(inode), frag.frag, mds);
if (ceph_mdsmap_get_state(mdsc->mdsmap, mds) >=
CEPH_MDS_STATE_ACTIVE) {
if (!ceph_mdsmap_is_laggy(mdsc->mdsmap,
@@ -1403,9 +1412,9 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
goto random;
}
mds = cap->session->s_mds;
- dout("%s %p %llx.%llx mds%d (%scap %p)\n", __func__,
- inode, ceph_vinop(inode), mds,
- cap == ci->i_auth_cap ? "auth " : "", cap);
+ doutc(cl, "%p %llx.%llx mds%d (%scap %p)\n", inode,
+ ceph_vinop(inode), mds,
+ cap == ci->i_auth_cap ? "auth " : "", cap);
spin_unlock(&ci->i_ceph_lock);
out:
iput(inode);
@@ -1416,7 +1425,7 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
*random = true;
mds = ceph_mdsmap_get_random_mds(mdsc->mdsmap);
- dout("%s chose random mds%d\n", __func__, mds);
+ doutc(cl, "chose random mds%d\n", mds);
return mds;
}
@@ -1529,6 +1538,7 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6
int metadata_key_count = 0;
struct ceph_options *opt = mdsc->fsc->client->options;
struct ceph_mount_options *fsopt = mdsc->fsc->mount_options;
+ struct ceph_client *cl = mdsc->fsc->client;
size_t size, count;
void *p, *end;
int ret;
@@ -1567,7 +1577,7 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6
msg = ceph_msg_new(CEPH_MSG_CLIENT_SESSION, sizeof(*h) + extra_bytes,
GFP_NOFS, false);
if (!msg) {
- pr_err("ENOMEM creating session open msg\n");
+ pr_err_client(cl, "ENOMEM creating session open msg\n");
return ERR_PTR(-ENOMEM);
}
p = msg->front.iov_base;
@@ -1607,14 +1617,14 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6
ret = encode_supported_features(&p, end);
if (ret) {
- pr_err("encode_supported_features failed!\n");
+ pr_err_client(cl, "encode_supported_features failed!\n");
ceph_msg_put(msg);
return ERR_PTR(ret);
}
ret = encode_metric_spec(&p, end);
if (ret) {
- pr_err("encode_metric_spec failed!\n");
+ pr_err_client(cl, "encode_metric_spec failed!\n");
ceph_msg_put(msg);
return ERR_PTR(ret);
}
@@ -1642,8 +1652,8 @@ static int __open_session(struct ceph_mds_client *mdsc,
/* wait for mds to go active? */
mstate = ceph_mdsmap_get_state(mdsc->mdsmap, mds);
- dout("open_session to mds%d (%s)\n", mds,
- ceph_mds_state_name(mstate));
+ doutc(mdsc->fsc->client, "open_session to mds%d (%s)\n", mds,
+ ceph_mds_state_name(mstate));
session->s_state = CEPH_MDS_SESSION_OPENING;
session->s_renew_requested = jiffies;
@@ -1686,8 +1696,9 @@ struct ceph_mds_session *
ceph_mdsc_open_export_target_session(struct ceph_mds_client *mdsc, int target)
{
struct ceph_mds_session *session;
+ struct ceph_client *cl = mdsc->fsc->client;
- dout("open_export_target_session to mds%d\n", target);
+ doutc(cl, "to mds%d\n", target);
mutex_lock(&mdsc->mutex);
session = __open_export_target_session(mdsc, target);
@@ -1702,13 +1713,14 @@ static void __open_export_target_sessions(struct ceph_mds_client *mdsc,
struct ceph_mds_info *mi;
struct ceph_mds_session *ts;
int i, mds = session->s_mds;
+ struct ceph_client *cl = mdsc->fsc->client;
if (mds >= mdsc->mdsmap->possible_max_rank)
return;
mi = &mdsc->mdsmap->m_info[mds];
- dout("open_export_target_sessions for mds%d (%d targets)\n",
- session->s_mds, mi->num_export_targets);
+ doutc(cl, "for mds%d (%d targets)\n", session->s_mds,
+ mi->num_export_targets);
for (i = 0; i < mi->num_export_targets; i++) {
ts = __open_export_target_session(mdsc, mi->export_targets[i]);
@@ -1731,11 +1743,13 @@ void ceph_mdsc_open_export_target_sessions(struct ceph_mds_client *mdsc,
static void detach_cap_releases(struct ceph_mds_session *session,
struct list_head *target)
{
+ struct ceph_client *cl = session->s_mdsc->fsc->client;
+
lockdep_assert_held(&session->s_cap_lock);
list_splice_init(&session->s_cap_releases, target);
session->s_num_cap_releases = 0;
- dout("dispose_cap_releases mds%d\n", session->s_mds);
+ doutc(cl, "mds%d\n", session->s_mds);
}
static void dispose_cap_releases(struct ceph_mds_client *mdsc,
@@ -1753,16 +1767,17 @@ static void dispose_cap_releases(struct ceph_mds_client *mdsc,
static void cleanup_session_requests(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mds_request *req;
struct rb_node *p;
- dout("cleanup_session_requests mds%d\n", session->s_mds);
+ doutc(cl, "mds%d\n", session->s_mds);
mutex_lock(&mdsc->mutex);
while (!list_empty(&session->s_unsafe)) {
req = list_first_entry(&session->s_unsafe,
struct ceph_mds_request, r_unsafe_item);
- pr_warn_ratelimited(" dropping unsafe request %llu\n",
- req->r_tid);
+ pr_warn_ratelimited_client(cl, " dropping unsafe request %llu\n",
+ req->r_tid);
if (req->r_target_inode)
mapping_set_error(req->r_target_inode->i_mapping, -EIO);
if (req->r_unsafe_dir)
@@ -1791,13 +1806,14 @@ int ceph_iterate_session_caps(struct ceph_mds_session *session,
int (*cb)(struct inode *, int mds, void *),
void *arg)
{
+ struct ceph_client *cl = session->s_mdsc->fsc->client;
struct list_head *p;
struct ceph_cap *cap;
struct inode *inode, *last_inode = NULL;
struct ceph_cap *old_cap = NULL;
int ret;
- dout("iterate_session_caps %p mds%d\n", session, session->s_mds);
+ doutc(cl, "%p mds%d\n", session, session->s_mds);
spin_lock(&session->s_cap_lock);
p = session->s_caps.next;
while (p != &session->s_caps) {
@@ -1828,8 +1844,7 @@ int ceph_iterate_session_caps(struct ceph_mds_session *session,
spin_lock(&session->s_cap_lock);
p = p->next;
if (!cap->ci) {
- dout("iterate_session_caps finishing cap %p removal\n",
- cap);
+ doutc(cl, "finishing cap %p removal\n", cap);
BUG_ON(cap->session != session);
cap->session = NULL;
list_del_init(&cap->session_caps);
@@ -1858,6 +1873,7 @@ int ceph_iterate_session_caps(struct ceph_mds_session *session,
static int remove_session_caps_cb(struct inode *inode, int mds, void *arg)
{
struct ceph_inode_info *ci = ceph_inode(inode);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
bool invalidate = false;
struct ceph_cap *cap;
int iputs = 0;
@@ -1865,8 +1881,8 @@ static int remove_session_caps_cb(struct inode *inode, int mds, void *arg)
spin_lock(&ci->i_ceph_lock);
cap = __get_cap_for_mds(ci, mds);
if (cap) {
- dout(" removing cap %p, ci is %p, inode is %p\n",
- cap, ci, &ci->netfs.inode);
+ doutc(cl, " removing cap %p, ci is %p, inode is %p\n",
+ cap, ci, &ci->netfs.inode);
iputs = ceph_purge_inode_cap(inode, cap, &invalidate);
}
@@ -1890,7 +1906,7 @@ static void remove_session_caps(struct ceph_mds_session *session)
struct super_block *sb = fsc->sb;
LIST_HEAD(dispose);
- dout("remove_session_caps on %p\n", session);
+ doutc(fsc->client, "on %p\n", session);
ceph_iterate_session_caps(session, remove_session_caps_cb, fsc);
wake_up_all(&fsc->mdsc->cap_flushing_wq);
@@ -1971,7 +1987,9 @@ static int wake_up_session_cb(struct inode *inode, int mds, void *arg)
static void wake_up_session_caps(struct ceph_mds_session *session, int ev)
{
- dout("wake_up_session_caps %p mds%d\n", session, session->s_mds);
+ struct ceph_client *cl = session->s_mdsc->fsc->client;
+
+ doutc(cl, "session %p mds%d\n", session, session->s_mds);
ceph_iterate_session_caps(session, wake_up_session_cb,
(void *)(unsigned long)ev);
}
@@ -1985,25 +2003,26 @@ static void wake_up_session_caps(struct ceph_mds_session *session, int ev)
static int send_renew_caps(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_msg *msg;
int state;
if (time_after_eq(jiffies, session->s_cap_ttl) &&
time_after_eq(session->s_cap_ttl, session->s_renew_requested))
- pr_info("mds%d caps stale\n", session->s_mds);
+ pr_info_client(cl, "mds%d caps stale\n", session->s_mds);
session->s_renew_requested = jiffies;
/* do not try to renew caps until a recovering mds has reconnected
* with its clients. */
state = ceph_mdsmap_get_state(mdsc->mdsmap, session->s_mds);
if (state < CEPH_MDS_STATE_RECONNECT) {
- dout("send_renew_caps ignoring mds%d (%s)\n",
- session->s_mds, ceph_mds_state_name(state));
+ doutc(cl, "ignoring mds%d (%s)\n", session->s_mds,
+ ceph_mds_state_name(state));
return 0;
}
- dout("send_renew_caps to mds%d (%s)\n", session->s_mds,
- ceph_mds_state_name(state));
+ doutc(cl, "to mds%d (%s)\n", session->s_mds,
+ ceph_mds_state_name(state));
msg = ceph_create_session_msg(CEPH_SESSION_REQUEST_RENEWCAPS,
++session->s_renew_seq);
if (!msg)
@@ -2015,10 +2034,11 @@ static int send_renew_caps(struct ceph_mds_client *mdsc,
static int send_flushmsg_ack(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session, u64 seq)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_msg *msg;
- dout("send_flushmsg_ack to mds%d (%s)s seq %lld\n",
- session->s_mds, ceph_session_state_name(session->s_state), seq);
+ doutc(cl, "to mds%d (%s)s seq %lld\n", session->s_mds,
+ ceph_session_state_name(session->s_state), seq);
msg = ceph_create_session_msg(CEPH_SESSION_FLUSHMSG_ACK, seq);
if (!msg)
return -ENOMEM;
@@ -2035,6 +2055,7 @@ static int send_flushmsg_ack(struct ceph_mds_client *mdsc,
static void renewed_caps(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session, int is_renew)
{
+ struct ceph_client *cl = mdsc->fsc->client;
int was_stale;
int wake = 0;
@@ -2046,15 +2067,17 @@ static void renewed_caps(struct ceph_mds_client *mdsc,
if (was_stale) {
if (time_before(jiffies, session->s_cap_ttl)) {
- pr_info("mds%d caps renewed\n", session->s_mds);
+ pr_info_client(cl, "mds%d caps renewed\n",
+ session->s_mds);
wake = 1;
} else {
- pr_info("mds%d caps still stale\n", session->s_mds);
+ pr_info_client(cl, "mds%d caps still stale\n",
+ session->s_mds);
}
}
- dout("renewed_caps mds%d ttl now %lu, was %s, now %s\n",
- session->s_mds, session->s_cap_ttl, was_stale ? "stale" : "fresh",
- time_before(jiffies, session->s_cap_ttl) ? "stale" : "fresh");
+ doutc(cl, "mds%d ttl now %lu, was %s, now %s\n", session->s_mds,
+ session->s_cap_ttl, was_stale ? "stale" : "fresh",
+ time_before(jiffies, session->s_cap_ttl) ? "stale" : "fresh");
spin_unlock(&session->s_cap_lock);
if (wake)
@@ -2066,11 +2089,11 @@ static void renewed_caps(struct ceph_mds_client *mdsc,
*/
static int request_close_session(struct ceph_mds_session *session)
{
+ struct ceph_client *cl = session->s_mdsc->fsc->client;
struct ceph_msg *msg;
- dout("request_close_session mds%d state %s seq %lld\n",
- session->s_mds, ceph_session_state_name(session->s_state),
- session->s_seq);
+ doutc(cl, "mds%d state %s seq %lld\n", session->s_mds,
+ ceph_session_state_name(session->s_state), session->s_seq);
msg = ceph_create_session_msg(CEPH_SESSION_REQUEST_CLOSE,
session->s_seq);
if (!msg)
@@ -2127,6 +2150,7 @@ static bool drop_negative_children(struct dentry *dentry)
static int trim_caps_cb(struct inode *inode, int mds, void *arg)
{
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
+ struct ceph_client *cl = mdsc->fsc->client;
int *remaining = arg;
struct ceph_inode_info *ci = ceph_inode(inode);
int used, wanted, oissued, mine;
@@ -2146,9 +2170,10 @@ static int trim_caps_cb(struct inode *inode, int mds, void *arg)
wanted = __ceph_caps_file_wanted(ci);
oissued = __ceph_caps_issued_other(ci, cap);
- dout("trim_caps_cb %p cap %p mine %s oissued %s used %s wanted %s\n",
- inode, cap, ceph_cap_string(mine), ceph_cap_string(oissued),
- ceph_cap_string(used), ceph_cap_string(wanted));
+ doutc(cl, "%p %llx.%llx cap %p mine %s oissued %s used %s wanted %s\n",
+ inode, ceph_vinop(inode), cap, ceph_cap_string(mine),
+ ceph_cap_string(oissued), ceph_cap_string(used),
+ ceph_cap_string(wanted));
if (cap == ci->i_auth_cap) {
if (ci->i_dirty_caps || ci->i_flushing_caps ||
!list_empty(&ci->i_cap_snaps))
@@ -2188,8 +2213,8 @@ static int trim_caps_cb(struct inode *inode, int mds, void *arg)
count = atomic_read(&inode->i_count);
if (count == 1)
(*remaining)--;
- dout("trim_caps_cb %p cap %p pruned, count now %d\n",
- inode, cap, count);
+ doutc(cl, "%p %llx.%llx cap %p pruned, count now %d\n",
+ inode, ceph_vinop(inode), cap, count);
} else {
dput(dentry);
}
@@ -2208,17 +2233,18 @@ int ceph_trim_caps(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session,
int max_caps)
{
+ struct ceph_client *cl = mdsc->fsc->client;
int trim_caps = session->s_nr_caps - max_caps;
- dout("trim_caps mds%d start: %d / %d, trim %d\n",
- session->s_mds, session->s_nr_caps, max_caps, trim_caps);
+ doutc(cl, "mds%d start: %d / %d, trim %d\n", session->s_mds,
+ session->s_nr_caps, max_caps, trim_caps);
if (trim_caps > 0) {
int remaining = trim_caps;
ceph_iterate_session_caps(session, trim_caps_cb, &remaining);
- dout("trim_caps mds%d done: %d / %d, trimmed %d\n",
- session->s_mds, session->s_nr_caps, max_caps,
- trim_caps - remaining);
+ doutc(cl, "mds%d done: %d / %d, trimmed %d\n",
+ session->s_mds, session->s_nr_caps, max_caps,
+ trim_caps - remaining);
}
ceph_flush_cap_releases(mdsc, session);
@@ -2228,6 +2254,7 @@ int ceph_trim_caps(struct ceph_mds_client *mdsc,
static int check_caps_flush(struct ceph_mds_client *mdsc,
u64 want_flush_tid)
{
+ struct ceph_client *cl = mdsc->fsc->client;
int ret = 1;
spin_lock(&mdsc->cap_dirty_lock);
@@ -2236,8 +2263,8 @@ static int check_caps_flush(struct ceph_mds_client *mdsc,
list_first_entry(&mdsc->cap_flush_list,
struct ceph_cap_flush, g_list);
if (cf->tid <= want_flush_tid) {
- dout("check_caps_flush still flushing tid "
- "%llu <= %llu\n", cf->tid, want_flush_tid);
+ doutc(cl, "still flushing tid %llu <= %llu\n",
+ cf->tid, want_flush_tid);
ret = 0;
}
}
@@ -2253,12 +2280,14 @@ static int check_caps_flush(struct ceph_mds_client *mdsc,
static void wait_caps_flush(struct ceph_mds_client *mdsc,
u64 want_flush_tid)
{
- dout("check_caps_flush want %llu\n", want_flush_tid);
+ struct ceph_client *cl = mdsc->fsc->client;
+
+ doutc(cl, "want %llu\n", want_flush_tid);
wait_event(mdsc->cap_flushing_wq,
check_caps_flush(mdsc, want_flush_tid));
- dout("check_caps_flush ok, flushed thru %llu\n", want_flush_tid);
+ doutc(cl, "ok, flushed thru %llu\n", want_flush_tid);
}
/*
@@ -2267,6 +2296,7 @@ static void wait_caps_flush(struct ceph_mds_client *mdsc,
static void ceph_send_cap_releases(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_msg *msg = NULL;
struct ceph_mds_cap_release *head;
struct ceph_mds_cap_item *item;
@@ -2325,7 +2355,7 @@ static void ceph_send_cap_releases(struct ceph_mds_client *mdsc,
msg->front.iov_len += sizeof(*cap_barrier);
msg->hdr.front_len = cpu_to_le32(msg->front.iov_len);
- dout("send_cap_releases mds%d %p\n", session->s_mds, msg);
+ doutc(cl, "mds%d %p\n", session->s_mds, msg);
ceph_con_send(&session->s_con, msg);
msg = NULL;
}
@@ -2345,13 +2375,13 @@ static void ceph_send_cap_releases(struct ceph_mds_client *mdsc,
msg->front.iov_len += sizeof(*cap_barrier);
msg->hdr.front_len = cpu_to_le32(msg->front.iov_len);
- dout("send_cap_releases mds%d %p\n", session->s_mds, msg);
+ doutc(cl, "mds%d %p\n", session->s_mds, msg);
ceph_con_send(&session->s_con, msg);
}
return;
out_err:
- pr_err("send_cap_releases mds%d, failed to allocate message\n",
- session->s_mds);
+ pr_err_client(cl, "mds%d, failed to allocate message\n",
+ session->s_mds);
spin_lock(&session->s_cap_lock);
list_splice(&tmp_list, &session->s_cap_releases);
session->s_num_cap_releases += num_cap_releases;
@@ -2374,16 +2404,17 @@ static void ceph_cap_release_work(struct work_struct *work)
void ceph_flush_cap_releases(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session)
{
+ struct ceph_client *cl = mdsc->fsc->client;
if (mdsc->stopping)
return;
ceph_get_mds_session(session);
if (queue_work(mdsc->fsc->cap_wq,
&session->s_cap_release_work)) {
- dout("cap release work queued\n");
+ doutc(cl, "cap release work queued\n");
} else {
ceph_put_mds_session(session);
- dout("failed to queue cap release work\n");
+ doutc(cl, "failed to queue cap release work\n");
}
}
@@ -2411,13 +2442,14 @@ static void ceph_cap_reclaim_work(struct work_struct *work)
void ceph_queue_cap_reclaim_work(struct ceph_mds_client *mdsc)
{
+ struct ceph_client *cl = mdsc->fsc->client;
if (mdsc->stopping)
return;
if (queue_work(mdsc->fsc->cap_wq, &mdsc->cap_reclaim_work)) {
- dout("caps reclaim work queued\n");
+ doutc(cl, "caps reclaim work queued\n");
} else {
- dout("failed to queue caps release work\n");
+ doutc(cl, "failed to queue caps release work\n");
}
}
@@ -2612,6 +2644,7 @@ static u8 *get_fscrypt_altname(const struct ceph_mds_request *req, u32 *plen)
char *ceph_mdsc_build_path(struct ceph_mds_client *mdsc, struct dentry *dentry,
int *plen, u64 *pbase, int for_wire)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct dentry *cur;
struct inode *inode;
char *path;
@@ -2637,8 +2670,7 @@ char *ceph_mdsc_build_path(struct ceph_mds_client *mdsc, struct dentry *dentry,
spin_lock(&cur->d_lock);
inode = d_inode(cur);
if (inode && ceph_snap(inode) == CEPH_SNAPDIR) {
- dout("build_path path+%d: %p SNAPDIR\n",
- pos, cur);
+ doutc(cl, "path+%d: %p SNAPDIR\n", pos, cur);
spin_unlock(&cur->d_lock);
parent = dget_parent(cur);
} else if (for_wire && inode && dentry != cur &&
@@ -2725,8 +2757,8 @@ char *ceph_mdsc_build_path(struct ceph_mds_client *mdsc, struct dentry *dentry,
*pbase = base;
*plen = PATH_MAX - 1 - pos;
- dout("build_path on %p %d built %llx '%.*s'\n",
- dentry, d_count(dentry), base, *plen, path + pos);
+ doutc(cl, "on %p %d built %llx '%.*s'\n", dentry, d_count(dentry),
+ base, *plen, path + pos);
return path + pos;
}
@@ -2789,22 +2821,22 @@ static int set_request_path_attr(struct ceph_mds_client *mdsc, struct inode *rin
int *pathlen, u64 *ino, bool *freepath,
bool parent_locked)
{
+ struct ceph_client *cl = mdsc->fsc->client;
int r = 0;
if (rinode) {
r = build_inode_path(rinode, ppath, pathlen, ino, freepath);
- dout(" inode %p %llx.%llx\n", rinode, ceph_ino(rinode),
- ceph_snap(rinode));
+ doutc(cl, " inode %p %llx.%llx\n", rinode, ceph_ino(rinode),
+ ceph_snap(rinode));
} else if (rdentry) {
r = build_dentry_path(mdsc, rdentry, rdiri, ppath, pathlen, ino,
freepath, parent_locked);
- dout(" dentry %p %llx/%.*s\n", rdentry, *ino, *pathlen,
- *ppath);
+ doutc(cl, " dentry %p %llx/%.*s\n", rdentry, *ino, *pathlen, *ppath);
} else if (rpath || rino) {
*ino = rino;
*ppath = rpath;
*pathlen = rpath ? strlen(rpath) : 0;
- dout(" path %.*s\n", *pathlen, rpath);
+ doutc(cl, " path %.*s\n", *pathlen, rpath);
}
return r;
@@ -3105,6 +3137,7 @@ static int __prepare_send_request(struct ceph_mds_session *session,
{
int mds = session->s_mds;
struct ceph_mds_client *mdsc = session->s_mdsc;
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mds_request_head_legacy *lhead;
struct ceph_mds_request_head *nhead;
struct ceph_msg *msg;
@@ -3123,8 +3156,8 @@ static int __prepare_send_request(struct ceph_mds_session *session,
old_max_retry = 1 << (old_max_retry * BITS_PER_BYTE);
if ((old_version && req->r_attempts >= old_max_retry) ||
((uint32_t)req->r_attempts >= U32_MAX)) {
- pr_warn_ratelimited("%s request tid %llu seq overflow\n",
- __func__, req->r_tid);
+ pr_warn_ratelimited_client(cl, "request tid %llu seq overflow\n",
+ req->r_tid);
return -EMULTIHOP;
}
}
@@ -3139,8 +3172,8 @@ static int __prepare_send_request(struct ceph_mds_session *session,
else
req->r_sent_on_mseq = -1;
}
- dout("%s %p tid %lld %s (attempt %d)\n", __func__, req,
- req->r_tid, ceph_mds_op_name(req->r_op), req->r_attempts);
+ doutc(cl, "%p tid %lld %s (attempt %d)\n", req, req->r_tid,
+ ceph_mds_op_name(req->r_op), req->r_attempts);
if (test_bit(CEPH_MDS_R_GOT_UNSAFE, &req->r_req_flags)) {
void *p;
@@ -3208,7 +3241,7 @@ static int __prepare_send_request(struct ceph_mds_session *session,
nhead->ext_num_retry = cpu_to_le32(req->r_attempts - 1);
}
- dout(" r_parent = %p\n", req->r_parent);
+ doutc(cl, " r_parent = %p\n", req->r_parent);
return 0;
}
@@ -3236,6 +3269,7 @@ static int __send_request(struct ceph_mds_session *session,
static void __do_request(struct ceph_mds_client *mdsc,
struct ceph_mds_request *req)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mds_session *session = NULL;
int mds = -1;
int err = 0;
@@ -3248,29 +3282,29 @@ static void __do_request(struct ceph_mds_client *mdsc,
}
if (READ_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_FENCE_IO) {
- dout("do_request metadata corrupted\n");
+ doutc(cl, "metadata corrupted\n");
err = -EIO;
goto finish;
}
if (req->r_timeout &&
time_after_eq(jiffies, req->r_started + req->r_timeout)) {
- dout("do_request timed out\n");
+ doutc(cl, "timed out\n");
err = -ETIMEDOUT;
goto finish;
}
if (READ_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_SHUTDOWN) {
- dout("do_request forced umount\n");
+ doutc(cl, "forced umount\n");
err = -EIO;
goto finish;
}
if (READ_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_MOUNTING) {
if (mdsc->mdsmap_err) {
err = mdsc->mdsmap_err;
- dout("do_request mdsmap err %d\n", err);
+ doutc(cl, "mdsmap err %d\n", err);
goto finish;
}
if (mdsc->mdsmap->m_epoch == 0) {
- dout("do_request no mdsmap, waiting for map\n");
+ doutc(cl, "no mdsmap, waiting for map\n");
list_add(&req->r_wait, &mdsc->waiting_for_map);
return;
}
@@ -3291,7 +3325,7 @@ static void __do_request(struct ceph_mds_client *mdsc,
err = -EJUKEBOX;
goto finish;
}
- dout("do_request no mds or not active, waiting for map\n");
+ doutc(cl, "no mds or not active, waiting for map\n");
list_add(&req->r_wait, &mdsc->waiting_for_map);
return;
}
@@ -3307,8 +3341,8 @@ static void __do_request(struct ceph_mds_client *mdsc,
}
req->r_session = ceph_get_mds_session(session);
- dout("do_request mds%d session %p state %s\n", mds, session,
- ceph_session_state_name(session->s_state));
+ doutc(cl, "mds%d session %p state %s\n", mds, session,
+ ceph_session_state_name(session->s_state));
/*
* The old ceph will crash the MDSs when see unknown OPs
@@ -3399,8 +3433,8 @@ static void __do_request(struct ceph_mds_client *mdsc,
spin_lock(&ci->i_ceph_lock);
cap = ci->i_auth_cap;
if (ci->i_ceph_flags & CEPH_I_ASYNC_CREATE && mds != cap->mds) {
- dout("do_request session changed for auth cap %d -> %d\n",
- cap->session->s_mds, session->s_mds);
+ doutc(cl, "session changed for auth cap %d -> %d\n",
+ cap->session->s_mds, session->s_mds);
/* Remove the auth cap from old session */
spin_lock(&cap->session->s_cap_lock);
@@ -3427,7 +3461,7 @@ static void __do_request(struct ceph_mds_client *mdsc,
ceph_put_mds_session(session);
finish:
if (err) {
- dout("__do_request early error %d\n", err);
+ doutc(cl, "early error %d\n", err);
req->r_err = err;
complete_request(mdsc, req);
__unregister_request(mdsc, req);
@@ -3441,6 +3475,7 @@ static void __do_request(struct ceph_mds_client *mdsc,
static void __wake_requests(struct ceph_mds_client *mdsc,
struct list_head *head)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mds_request *req;
LIST_HEAD(tmp_list);
@@ -3450,7 +3485,8 @@ static void __wake_requests(struct ceph_mds_client *mdsc,
req = list_entry(tmp_list.next,
struct ceph_mds_request, r_wait);
list_del_init(&req->r_wait);
- dout(" wake request %p tid %llu\n", req, req->r_tid);
+ doutc(cl, " wake request %p tid %llu\n", req,
+ req->r_tid);
__do_request(mdsc, req);
}
}
@@ -3461,10 +3497,11 @@ static void __wake_requests(struct ceph_mds_client *mdsc,
*/
static void kick_requests(struct ceph_mds_client *mdsc, int mds)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mds_request *req;
struct rb_node *p = rb_first(&mdsc->request_tree);
- dout("kick_requests mds%d\n", mds);
+ doutc(cl, "kick_requests mds%d\n", mds);
while (p) {
req = rb_entry(p, struct ceph_mds_request, r_node);
p = rb_next(p);
@@ -3474,7 +3511,7 @@ static void kick_requests(struct ceph_mds_client *mdsc, int mds)
continue; /* only new requests */
if (req->r_session &&
req->r_session->s_mds == mds) {
- dout(" kicking tid %llu\n", req->r_tid);
+ doutc(cl, " kicking tid %llu\n", req->r_tid);
list_del_init(&req->r_wait);
__do_request(mdsc, req);
}
@@ -3484,6 +3521,7 @@ static void kick_requests(struct ceph_mds_client *mdsc, int mds)
int ceph_mdsc_submit_request(struct ceph_mds_client *mdsc, struct inode *dir,
struct ceph_mds_request *req)
{
+ struct ceph_client *cl = mdsc->fsc->client;
int err = 0;
/* take CAP_PIN refs for r_inode, r_parent, r_old_dentry */
@@ -3505,8 +3543,7 @@ int ceph_mdsc_submit_request(struct ceph_mds_client *mdsc, struct inode *dir,
if (req->r_inode) {
err = ceph_wait_on_async_create(req->r_inode);
if (err) {
- dout("%s: wait for async create returned: %d\n",
- __func__, err);
+ doutc(cl, "wait for async create returned: %d\n", err);
return err;
}
}
@@ -3514,13 +3551,12 @@ int ceph_mdsc_submit_request(struct ceph_mds_client *mdsc, struct inode *dir,
if (!err && req->r_old_inode) {
err = ceph_wait_on_async_create(req->r_old_inode);
if (err) {
- dout("%s: wait for async create returned: %d\n",
- __func__, err);
+ doutc(cl, "wait for async create returned: %d\n", err);
return err;
}
}
- dout("submit_request on %p for inode %p\n", req, dir);
+ doutc(cl, "submit_request on %p for inode %p\n", req, dir);
mutex_lock(&mdsc->mutex);
__register_request(mdsc, req, dir);
__do_request(mdsc, req);
@@ -3533,10 +3569,11 @@ int ceph_mdsc_wait_request(struct ceph_mds_client *mdsc,
struct ceph_mds_request *req,
ceph_mds_request_wait_callback_t wait_func)
{
+ struct ceph_client *cl = mdsc->fsc->client;
int err;
/* wait */
- dout("do_request waiting\n");
+ doutc(cl, "do_request waiting\n");
if (wait_func) {
err = wait_func(mdsc, req);
} else {
@@ -3550,14 +3587,14 @@ int ceph_mdsc_wait_request(struct ceph_mds_client *mdsc,
else
err = timeleft; /* killed */
}
- dout("do_request waited, got %d\n", err);
+ doutc(cl, "do_request waited, got %d\n", err);
mutex_lock(&mdsc->mutex);
/* only abort if we didn't race with a real reply */
if (test_bit(CEPH_MDS_R_GOT_RESULT, &req->r_req_flags)) {
err = le32_to_cpu(req->r_reply_info.head->result);
} else if (err < 0) {
- dout("aborted request %lld with %d\n", req->r_tid, err);
+ doutc(cl, "aborted request %lld with %d\n", req->r_tid, err);
/*
* ensure we aren't running concurrently with
@@ -3588,15 +3625,16 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
struct inode *dir,
struct ceph_mds_request *req)
{
+ struct ceph_client *cl = mdsc->fsc->client;
int err;
- dout("do_request on %p\n", req);
+ doutc(cl, "do_request on %p\n", req);
/* issue */
err = ceph_mdsc_submit_request(mdsc, dir, req);
if (!err)
err = ceph_mdsc_wait_request(mdsc, req, NULL);
- dout("do_request %p done, result %d\n", req, err);
+ doutc(cl, "do_request %p done, result %d\n", req, err);
return err;
}
@@ -3608,8 +3646,10 @@ void ceph_invalidate_dir_request(struct ceph_mds_request *req)
{
struct inode *dir = req->r_parent;
struct inode *old_dir = req->r_old_dentry_dir;
+ struct ceph_client *cl = req->r_mdsc->fsc->client;
- dout("invalidate_dir_request %p %p (complete, lease(s))\n", dir, old_dir);
+ doutc(cl, "invalidate_dir_request %p %p (complete, lease(s))\n",
+ dir, old_dir);
ceph_dir_clear_complete(dir);
if (old_dir)
@@ -3630,6 +3670,7 @@ void ceph_invalidate_dir_request(struct ceph_mds_request *req)
static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
{
struct ceph_mds_client *mdsc = session->s_mdsc;
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mds_request *req;
struct ceph_mds_reply_head *head = msg->front.iov_base;
struct ceph_mds_reply_info_parsed *rinfo; /* parsed reply info */
@@ -3640,7 +3681,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
bool close_sessions = false;
if (msg->front.iov_len < sizeof(*head)) {
- pr_err("mdsc_handle_reply got corrupt (short) reply\n");
+ pr_err_client(cl, "got corrupt (short) reply\n");
ceph_msg_dump(msg);
return;
}
@@ -3650,17 +3691,17 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
mutex_lock(&mdsc->mutex);
req = lookup_get_request(mdsc, tid);
if (!req) {
- dout("handle_reply on unknown tid %llu\n", tid);
+ doutc(cl, "on unknown tid %llu\n", tid);
mutex_unlock(&mdsc->mutex);
return;
}
- dout("handle_reply %p\n", req);
+ doutc(cl, "handle_reply %p\n", req);
/* correct session? */
if (req->r_session != session) {
- pr_err("mdsc_handle_reply got %llu on session mds%d"
- " not mds%d\n", tid, session->s_mds,
- req->r_session ? req->r_session->s_mds : -1);
+ pr_err_client(cl, "got %llu on session mds%d not mds%d\n",
+ tid, session->s_mds,
+ req->r_session ? req->r_session->s_mds : -1);
mutex_unlock(&mdsc->mutex);
goto out;
}
@@ -3668,14 +3709,14 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
/* dup? */
if ((test_bit(CEPH_MDS_R_GOT_UNSAFE, &req->r_req_flags) && !head->safe) ||
(test_bit(CEPH_MDS_R_GOT_SAFE, &req->r_req_flags) && head->safe)) {
- pr_warn("got a dup %s reply on %llu from mds%d\n",
- head->safe ? "safe" : "unsafe", tid, mds);
+ pr_warn_client(cl, "got a dup %s reply on %llu from mds%d\n",
+ head->safe ? "safe" : "unsafe", tid, mds);
mutex_unlock(&mdsc->mutex);
goto out;
}
if (test_bit(CEPH_MDS_R_GOT_SAFE, &req->r_req_flags)) {
- pr_warn("got unsafe after safe on %llu from mds%d\n",
- tid, mds);
+ pr_warn_client(cl, "got unsafe after safe on %llu from mds%d\n",
+ tid, mds);
mutex_unlock(&mdsc->mutex);
goto out;
}
@@ -3698,7 +3739,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
* response. And even if it did, there is nothing
* useful we could do with a revised return value.
*/
- dout("got safe reply %llu, mds%d\n", tid, mds);
+ doutc(cl, "got safe reply %llu, mds%d\n", tid, mds);
mutex_unlock(&mdsc->mutex);
goto out;
@@ -3708,7 +3749,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
list_add_tail(&req->r_unsafe_item, &req->r_session->s_unsafe);
}
- dout("handle_reply tid %lld result %d\n", tid, result);
+ doutc(cl, "tid %lld result %d\n", tid, result);
if (test_bit(CEPHFS_FEATURE_REPLY_ENCODING, &session->s_features))
err = parse_reply_info(session, msg, req, (u64)-1);
else
@@ -3748,7 +3789,8 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
mutex_lock(&session->s_mutex);
if (err < 0) {
- pr_err("mdsc_handle_reply got corrupt reply mds%d(tid:%lld)\n", mds, tid);
+ pr_err_client(cl, "got corrupt reply mds%d(tid:%lld)\n",
+ mds, tid);
ceph_msg_dump(msg);
goto out_err;
}
@@ -3812,7 +3854,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
set_bit(CEPH_MDS_R_GOT_RESULT, &req->r_req_flags);
}
} else {
- dout("reply arrived after request %lld was aborted\n", tid);
+ doutc(cl, "reply arrived after request %lld was aborted\n", tid);
}
mutex_unlock(&mdsc->mutex);
@@ -3841,6 +3883,7 @@ static void handle_forward(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session,
struct ceph_msg *msg)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mds_request *req;
u64 tid = le64_to_cpu(msg->hdr.tid);
u32 next_mds;
@@ -3858,12 +3901,12 @@ static void handle_forward(struct ceph_mds_client *mdsc,
req = lookup_get_request(mdsc, tid);
if (!req) {
mutex_unlock(&mdsc->mutex);
- dout("forward tid %llu to mds%d - req dne\n", tid, next_mds);
+ doutc(cl, "forward tid %llu to mds%d - req dne\n", tid, next_mds);
return; /* dup reply? */
}
if (test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags)) {
- dout("forward tid %llu aborted, unregistering\n", tid);
+ doutc(cl, "forward tid %llu aborted, unregistering\n", tid);
__unregister_request(mdsc, req);
} else if (fwd_seq <= req->r_num_fwd || (uint32_t)fwd_seq >= U32_MAX) {
/*
@@ -3879,10 +3922,11 @@ static void handle_forward(struct ceph_mds_client *mdsc,
set_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags);
mutex_unlock(&req->r_fill_mutex);
aborted = true;
- pr_warn_ratelimited("forward tid %llu seq overflow\n", tid);
+ pr_warn_ratelimited_client(cl, "forward tid %llu seq overflow\n",
+ tid);
} else {
/* resend. forward race not possible; mds would drop */
- dout("forward tid %llu to mds%d (we resend)\n", tid, next_mds);
+ doutc(cl, "forward tid %llu to mds%d (we resend)\n", tid, next_mds);
BUG_ON(req->r_err);
BUG_ON(test_bit(CEPH_MDS_R_GOT_RESULT, &req->r_req_flags));
req->r_attempts = 0;
@@ -3900,7 +3944,7 @@ static void handle_forward(struct ceph_mds_client *mdsc,
return;
bad:
- pr_err("mdsc_handle_forward decode error err=%d\n", err);
+ pr_err_client(cl, "decode error err=%d\n", err);
ceph_msg_dump(msg);
}
@@ -3939,6 +3983,7 @@ static void handle_session(struct ceph_mds_session *session,
struct ceph_msg *msg)
{
struct ceph_mds_client *mdsc = session->s_mdsc;
+ struct ceph_client *cl = mdsc->fsc->client;
int mds = session->s_mds;
int msg_version = le16_to_cpu(msg->hdr.version);
void *p = msg->front.iov_base;
@@ -3986,7 +4031,8 @@ static void handle_session(struct ceph_mds_session *session,
/* version >= 5, flags */
ceph_decode_32_safe(&p, end, flags, bad);
if (flags & CEPH_SESSION_BLOCKLISTED) {
- pr_warn("mds%d session blocklisted\n", session->s_mds);
+ pr_warn_client(cl, "mds%d session blocklisted\n",
+ session->s_mds);
blocklisted = true;
}
}
@@ -4002,23 +4048,25 @@ static void handle_session(struct ceph_mds_session *session,
mutex_lock(&session->s_mutex);
- dout("handle_session mds%d %s %p state %s seq %llu\n",
- mds, ceph_session_op_name(op), session,
- ceph_session_state_name(session->s_state), seq);
+ doutc(cl, "mds%d %s %p state %s seq %llu\n", mds,
+ ceph_session_op_name(op), session,
+ ceph_session_state_name(session->s_state), seq);
if (session->s_state == CEPH_MDS_SESSION_HUNG) {
session->s_state = CEPH_MDS_SESSION_OPEN;
- pr_info("mds%d came back\n", session->s_mds);
+ pr_info_client(cl, "mds%d came back\n", session->s_mds);
}
switch (op) {
case CEPH_SESSION_OPEN:
if (session->s_state == CEPH_MDS_SESSION_RECONNECTING)
- pr_info("mds%d reconnect success\n", session->s_mds);
+ pr_info_client(cl, "mds%d reconnect success\n",
+ session->s_mds);
session->s_features = features;
if (session->s_state == CEPH_MDS_SESSION_OPEN) {
- pr_notice("mds%d is already opened\n", session->s_mds);
+ pr_notice_client(cl, "mds%d is already opened\n",
+ session->s_mds);
} else {
session->s_state = CEPH_MDS_SESSION_OPEN;
renewed_caps(mdsc, session, 0);
@@ -4047,7 +4095,8 @@ static void handle_session(struct ceph_mds_session *session,
case CEPH_SESSION_CLOSE:
if (session->s_state == CEPH_MDS_SESSION_RECONNECTING)
- pr_info("mds%d reconnect denied\n", session->s_mds);
+ pr_info_client(cl, "mds%d reconnect denied\n",
+ session->s_mds);
session->s_state = CEPH_MDS_SESSION_CLOSED;
cleanup_session_requests(mdsc, session);
remove_session_caps(session);
@@ -4056,8 +4105,8 @@ static void handle_session(struct ceph_mds_session *session,
break;
case CEPH_SESSION_STALE:
- pr_info("mds%d caps went stale, renewing\n",
- session->s_mds);
+ pr_info_client(cl, "mds%d caps went stale, renewing\n",
+ session->s_mds);
atomic_inc(&session->s_cap_gen);
session->s_cap_ttl = jiffies - 1;
send_renew_caps(mdsc, session);
@@ -4078,7 +4127,7 @@ static void handle_session(struct ceph_mds_session *session,
break;
case CEPH_SESSION_FORCE_RO:
- dout("force_session_readonly %p\n", session);
+ doutc(cl, "force_session_readonly %p\n", session);
spin_lock(&session->s_cap_lock);
session->s_readonly = true;
spin_unlock(&session->s_cap_lock);
@@ -4087,7 +4136,8 @@ static void handle_session(struct ceph_mds_session *session,
case CEPH_SESSION_REJECT:
WARN_ON(session->s_state != CEPH_MDS_SESSION_OPENING);
- pr_info("mds%d rejected session\n", session->s_mds);
+ pr_info_client(cl, "mds%d rejected session\n",
+ session->s_mds);
session->s_state = CEPH_MDS_SESSION_REJECTED;
cleanup_session_requests(mdsc, session);
remove_session_caps(session);
@@ -4097,7 +4147,7 @@ static void handle_session(struct ceph_mds_session *session,
break;
default:
- pr_err("mdsc_handle_session bad op %d mds%d\n", op, mds);
+ pr_err_client(cl, "bad op %d mds%d\n", op, mds);
WARN_ON(1);
}
@@ -4114,30 +4164,32 @@ static void handle_session(struct ceph_mds_session *session,
return;
bad:
- pr_err("mdsc_handle_session corrupt message mds%d len %d\n", mds,
- (int)msg->front.iov_len);
+ pr_err_client(cl, "corrupt message mds%d len %d\n", mds,
+ (int)msg->front.iov_len);
ceph_msg_dump(msg);
return;
}
void ceph_mdsc_release_dir_caps(struct ceph_mds_request *req)
{
+ struct ceph_client *cl = req->r_mdsc->fsc->client;
int dcaps;
dcaps = xchg(&req->r_dir_caps, 0);
if (dcaps) {
- dout("releasing r_dir_caps=%s\n", ceph_cap_string(dcaps));
+ doutc(cl, "releasing r_dir_caps=%s\n", ceph_cap_string(dcaps));
ceph_put_cap_refs(ceph_inode(req->r_parent), dcaps);
}
}
void ceph_mdsc_release_dir_caps_no_check(struct ceph_mds_request *req)
{
+ struct ceph_client *cl = req->r_mdsc->fsc->client;
int dcaps;
dcaps = xchg(&req->r_dir_caps, 0);
if (dcaps) {
- dout("releasing r_dir_caps=%s\n", ceph_cap_string(dcaps));
+ doutc(cl, "releasing r_dir_caps=%s\n", ceph_cap_string(dcaps));
ceph_put_cap_refs_no_check_caps(ceph_inode(req->r_parent),
dcaps);
}
@@ -4152,7 +4204,7 @@ static void replay_unsafe_requests(struct ceph_mds_client *mdsc,
struct ceph_mds_request *req, *nreq;
struct rb_node *p;
- dout("replay_unsafe_requests mds%d\n", session->s_mds);
+ doutc(mdsc->fsc->client, "mds%d\n", session->s_mds);
mutex_lock(&mdsc->mutex);
list_for_each_entry_safe(req, nreq, &session->s_unsafe, r_unsafe_item)
@@ -4297,6 +4349,7 @@ static struct dentry* d_find_primary(struct inode *inode)
static int reconnect_caps_cb(struct inode *inode, int mds, void *arg)
{
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
union {
struct ceph_mds_cap_reconnect v2;
struct ceph_mds_cap_reconnect_v1 v1;
@@ -4333,9 +4386,9 @@ static int reconnect_caps_cb(struct inode *inode, int mds, void *arg)
err = 0;
goto out_err;
}
- dout(" adding %p ino %llx.%llx cap %p %lld %s\n",
- inode, ceph_vinop(inode), cap, cap->cap_id,
- ceph_cap_string(cap->issued));
+ doutc(cl, " adding %p ino %llx.%llx cap %p %lld %s\n", inode,
+ ceph_vinop(inode), cap, cap->cap_id,
+ ceph_cap_string(cap->issued));
cap->seq = 0; /* reset cap seq */
cap->issue_seq = 0; /* and issue_seq */
@@ -4485,6 +4538,7 @@ static int encode_snap_realms(struct ceph_mds_client *mdsc,
{
struct rb_node *p;
struct ceph_pagelist *pagelist = recon_state->pagelist;
+ struct ceph_client *cl = mdsc->fsc->client;
int err = 0;
if (recon_state->msg_version >= 4) {
@@ -4523,8 +4577,8 @@ static int encode_snap_realms(struct ceph_mds_client *mdsc,
ceph_pagelist_encode_32(pagelist, sizeof(sr_rec));
}
- dout(" adding snap realm %llx seq %lld parent %llx\n",
- realm->ino, realm->seq, realm->parent_ino);
+ doutc(cl, " adding snap realm %llx seq %lld parent %llx\n",
+ realm->ino, realm->seq, realm->parent_ino);
sr_rec.ino = cpu_to_le64(realm->ino);
sr_rec.seq = cpu_to_le64(realm->seq);
sr_rec.parent = cpu_to_le64(realm->parent_ino);
@@ -4553,6 +4607,7 @@ static int encode_snap_realms(struct ceph_mds_client *mdsc,
static void send_mds_reconnect(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_msg *reply;
int mds = session->s_mds;
int err = -ENOMEM;
@@ -4561,7 +4616,7 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc,
};
LIST_HEAD(dispose);
- pr_info("mds%d reconnect start\n", mds);
+ pr_info_client(cl, "mds%d reconnect start\n", mds);
recon_state.pagelist = ceph_pagelist_alloc(GFP_NOFS);
if (!recon_state.pagelist)
@@ -4577,8 +4632,8 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc,
session->s_state = CEPH_MDS_SESSION_RECONNECTING;
session->s_seq = 0;
- dout("session %p state %s\n", session,
- ceph_session_state_name(session->s_state));
+ doutc(cl, "session %p state %s\n", session,
+ ceph_session_state_name(session->s_state));
atomic_inc(&session->s_cap_gen);
@@ -4712,7 +4767,8 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc,
fail_nomsg:
ceph_pagelist_release(recon_state.pagelist);
fail_nopagelist:
- pr_err("error %d preparing reconnect for mds%d\n", err, mds);
+ pr_err_client(cl, "error %d preparing reconnect for mds%d\n",
+ err, mds);
return;
}
@@ -4731,9 +4787,9 @@ static void check_new_map(struct ceph_mds_client *mdsc,
int oldstate, newstate;
struct ceph_mds_session *s;
unsigned long targets[DIV_ROUND_UP(CEPH_MAX_MDS, sizeof(unsigned long))] = {0};
+ struct ceph_client *cl = mdsc->fsc->client;
- dout("check_new_map new %u old %u\n",
- newmap->m_epoch, oldmap->m_epoch);
+ doutc(cl, "new %u old %u\n", newmap->m_epoch, oldmap->m_epoch);
if (newmap->m_info) {
for (i = 0; i < newmap->possible_max_rank; i++) {
@@ -4749,12 +4805,12 @@ static void check_new_map(struct ceph_mds_client *mdsc,
oldstate = ceph_mdsmap_get_state(oldmap, i);
newstate = ceph_mdsmap_get_state(newmap, i);
- dout("check_new_map mds%d state %s%s -> %s%s (session %s)\n",
- i, ceph_mds_state_name(oldstate),
- ceph_mdsmap_is_laggy(oldmap, i) ? " (laggy)" : "",
- ceph_mds_state_name(newstate),
- ceph_mdsmap_is_laggy(newmap, i) ? " (laggy)" : "",
- ceph_session_state_name(s->s_state));
+ doutc(cl, "mds%d state %s%s -> %s%s (session %s)\n",
+ i, ceph_mds_state_name(oldstate),
+ ceph_mdsmap_is_laggy(oldmap, i) ? " (laggy)" : "",
+ ceph_mds_state_name(newstate),
+ ceph_mdsmap_is_laggy(newmap, i) ? " (laggy)" : "",
+ ceph_session_state_name(s->s_state));
if (i >= newmap->possible_max_rank) {
/* force close session for stopped mds */
@@ -4807,7 +4863,8 @@ static void check_new_map(struct ceph_mds_client *mdsc,
newstate >= CEPH_MDS_STATE_ACTIVE) {
if (oldstate != CEPH_MDS_STATE_CREATING &&
oldstate != CEPH_MDS_STATE_STARTING)
- pr_info("mds%d recovery completed\n", s->s_mds);
+ pr_info_client(cl, "mds%d recovery completed\n",
+ s->s_mds);
kick_requests(mdsc, i);
mutex_unlock(&mdsc->mutex);
mutex_lock(&s->s_mutex);
@@ -4851,12 +4908,13 @@ static void check_new_map(struct ceph_mds_client *mdsc,
s = __open_export_target_session(mdsc, i);
if (IS_ERR(s)) {
err = PTR_ERR(s);
- pr_err("failed to open export target session, err %d\n",
- err);
+ pr_err_client(cl,
+ "failed to open export target session, err %d\n",
+ err);
continue;
}
}
- dout("send reconnect to export target mds.%d\n", i);
+ doutc(cl, "send reconnect to export target mds.%d\n", i);
mutex_unlock(&mdsc->mutex);
send_mds_reconnect(mdsc, s);
ceph_put_mds_session(s);
@@ -4872,8 +4930,7 @@ static void check_new_map(struct ceph_mds_client *mdsc,
if (s->s_state == CEPH_MDS_SESSION_OPEN ||
s->s_state == CEPH_MDS_SESSION_HUNG ||
s->s_state == CEPH_MDS_SESSION_CLOSING) {
- dout(" connecting to export targets of laggy mds%d\n",
- i);
+ doutc(cl, " connecting to export targets of laggy mds%d\n", i);
__open_export_target_sessions(mdsc, s);
}
}
@@ -4900,6 +4957,7 @@ static void handle_lease(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session,
struct ceph_msg *msg)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct super_block *sb = mdsc->fsc->sb;
struct inode *inode;
struct dentry *parent, *dentry;
@@ -4911,7 +4969,7 @@ static void handle_lease(struct ceph_mds_client *mdsc,
struct qstr dname;
int release = 0;
- dout("handle_lease from mds%d\n", mds);
+ doutc(cl, "from mds%d\n", mds);
if (!ceph_inc_mds_stopping_blocker(mdsc, session))
return;
@@ -4929,20 +4987,19 @@ static void handle_lease(struct ceph_mds_client *mdsc,
/* lookup inode */
inode = ceph_find_inode(sb, vino);
- dout("handle_lease %s, ino %llx %p %.*s\n",
- ceph_lease_op_name(h->action), vino.ino, inode,
- dname.len, dname.name);
+ doutc(cl, "%s, ino %llx %p %.*s\n", ceph_lease_op_name(h->action),
+ vino.ino, inode, dname.len, dname.name);
mutex_lock(&session->s_mutex);
if (!inode) {
- dout("handle_lease no inode %llx\n", vino.ino);
+ doutc(cl, "no inode %llx\n", vino.ino);
goto release;
}
/* dentry */
parent = d_find_alias(inode);
if (!parent) {
- dout("no parent dentry on inode %p\n", inode);
+ doutc(cl, "no parent dentry on inode %p\n", inode);
WARN_ON(1);
goto release; /* hrm... */
}
@@ -5002,7 +5059,7 @@ static void handle_lease(struct ceph_mds_client *mdsc,
bad:
ceph_dec_mds_stopping_blocker(mdsc);
- pr_err("corrupt lease message\n");
+ pr_err_client(cl, "corrupt lease message\n");
ceph_msg_dump(msg);
}
@@ -5010,13 +5067,14 @@ void ceph_mdsc_lease_send_msg(struct ceph_mds_session *session,
struct dentry *dentry, char action,
u32 seq)
{
+ struct ceph_client *cl = session->s_mdsc->fsc->client;
struct ceph_msg *msg;
struct ceph_mds_lease *lease;
struct inode *dir;
int len = sizeof(*lease) + sizeof(u32) + NAME_MAX;
- dout("lease_send_msg identry %p %s to mds%d\n",
- dentry, ceph_lease_op_name(action), session->s_mds);
+ doutc(cl, "identry %p %s to mds%d\n", dentry, ceph_lease_op_name(action),
+ session->s_mds);
msg = ceph_msg_new(CEPH_MSG_CLIENT_LEASE, len, GFP_NOFS, false);
if (!msg)
@@ -5049,6 +5107,7 @@ static void lock_unlock_session(struct ceph_mds_session *s)
static void maybe_recover_session(struct ceph_mds_client *mdsc)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_fs_client *fsc = mdsc->fsc;
if (!ceph_test_mount_opt(fsc, CLEANRECOVER))
@@ -5060,17 +5119,19 @@ static void maybe_recover_session(struct ceph_mds_client *mdsc)
if (!READ_ONCE(fsc->blocklisted))
return;
- pr_info("auto reconnect after blocklisted\n");
+ pr_info_client(cl, "auto reconnect after blocklisted\n");
ceph_force_reconnect(fsc->sb);
}
bool check_session_state(struct ceph_mds_session *s)
{
+ struct ceph_client *cl = s->s_mdsc->fsc->client;
+
switch (s->s_state) {
case CEPH_MDS_SESSION_OPEN:
if (s->s_ttl && time_after(jiffies, s->s_ttl)) {
s->s_state = CEPH_MDS_SESSION_HUNG;
- pr_info("mds%d hung\n", s->s_mds);
+ pr_info_client(cl, "mds%d hung\n", s->s_mds);
}
break;
case CEPH_MDS_SESSION_CLOSING:
@@ -5090,6 +5151,8 @@ bool check_session_state(struct ceph_mds_session *s)
*/
void inc_session_sequence(struct ceph_mds_session *s)
{
+ struct ceph_client *cl = s->s_mdsc->fsc->client;
+
lockdep_assert_held(&s->s_mutex);
s->s_seq++;
@@ -5097,11 +5160,11 @@ void inc_session_sequence(struct ceph_mds_session *s)
if (s->s_state == CEPH_MDS_SESSION_CLOSING) {
int ret;
- dout("resending session close request for mds%d\n", s->s_mds);
+ doutc(cl, "resending session close request for mds%d\n", s->s_mds);
ret = request_close_session(s);
if (ret < 0)
- pr_err("unable to close session to mds%d: %d\n",
- s->s_mds, ret);
+ pr_err_client(cl, "unable to close session to mds%d: %d\n",
+ s->s_mds, ret);
}
}
@@ -5130,7 +5193,7 @@ static void delayed_work(struct work_struct *work)
int renew_caps;
int i;
- dout("mdsc delayed_work\n");
+ doutc(mdsc->fsc->client, "mdsc delayed_work\n");
if (mdsc->stopping >= CEPH_MDSC_STOPPING_FLUSHED)
return;
@@ -5259,6 +5322,7 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc)
*/
static void wait_requests(struct ceph_mds_client *mdsc)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_options *opts = mdsc->fsc->client->options;
struct ceph_mds_request *req;
@@ -5266,25 +5330,25 @@ static void wait_requests(struct ceph_mds_client *mdsc)
if (__get_oldest_req(mdsc)) {
mutex_unlock(&mdsc->mutex);
- dout("wait_requests waiting for requests\n");
+ doutc(cl, "waiting for requests\n");
wait_for_completion_timeout(&mdsc->safe_umount_waiters,
ceph_timeout_jiffies(opts->mount_timeout));
/* tear down remaining requests */
mutex_lock(&mdsc->mutex);
while ((req = __get_oldest_req(mdsc))) {
- dout("wait_requests timed out on tid %llu\n",
- req->r_tid);
+ doutc(cl, "timed out on tid %llu\n", req->r_tid);
list_del_init(&req->r_wait);
__unregister_request(mdsc, req);
}
}
mutex_unlock(&mdsc->mutex);
- dout("wait_requests done\n");
+ doutc(cl, "done\n");
}
void send_flush_mdlog(struct ceph_mds_session *s)
{
+ struct ceph_client *cl = s->s_mdsc->fsc->client;
struct ceph_msg *msg;
/*
@@ -5294,13 +5358,13 @@ void send_flush_mdlog(struct ceph_mds_session *s)
return;
mutex_lock(&s->s_mutex);
- dout("request mdlog flush to mds%d (%s)s seq %lld\n", s->s_mds,
- ceph_session_state_name(s->s_state), s->s_seq);
+ doutc(cl, "request mdlog flush to mds%d (%s)s seq %lld\n",
+ s->s_mds, ceph_session_state_name(s->s_state), s->s_seq);
msg = ceph_create_session_msg(CEPH_SESSION_REQUEST_FLUSH_MDLOG,
s->s_seq);
if (!msg) {
- pr_err("failed to request mdlog flush to mds%d (%s) seq %lld\n",
- s->s_mds, ceph_session_state_name(s->s_state), s->s_seq);
+ pr_err_client(cl, "failed to request mdlog flush to mds%d (%s) seq %lld\n",
+ s->s_mds, ceph_session_state_name(s->s_state), s->s_seq);
} else {
ceph_con_send(&s->s_con, msg);
}
@@ -5313,7 +5377,7 @@ void send_flush_mdlog(struct ceph_mds_session *s)
*/
void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc)
{
- dout("pre_umount\n");
+ doutc(mdsc->fsc->client, "begin\n");
mdsc->stopping = CEPH_MDSC_STOPPING_BEGIN;
ceph_mdsc_iterate_sessions(mdsc, send_flush_mdlog, true);
@@ -5328,6 +5392,7 @@ void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc)
ceph_msgr_flush();
ceph_cleanup_quotarealms_inodes(mdsc);
+ doutc(mdsc->fsc->client, "done\n");
}
/*
@@ -5336,12 +5401,13 @@ void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc)
static void flush_mdlog_and_wait_mdsc_unsafe_requests(struct ceph_mds_client *mdsc,
u64 want_tid)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mds_request *req = NULL, *nextreq;
struct ceph_mds_session *last_session = NULL;
struct rb_node *n;
mutex_lock(&mdsc->mutex);
- dout("%s want %lld\n", __func__, want_tid);
+ doutc(cl, "want %lld\n", want_tid);
restart:
req = __get_oldest_req(mdsc);
while (req && req->r_tid <= want_tid) {
@@ -5375,8 +5441,8 @@ static void flush_mdlog_and_wait_mdsc_unsafe_requests(struct ceph_mds_client *md
} else {
ceph_put_mds_session(s);
}
- dout("%s wait on %llu (want %llu)\n", __func__,
- req->r_tid, want_tid);
+ doutc(cl, "wait on %llu (want %llu)\n",
+ req->r_tid, want_tid);
wait_for_completion(&req->r_safe_completion);
mutex_lock(&mdsc->mutex);
@@ -5394,17 +5460,18 @@ static void flush_mdlog_and_wait_mdsc_unsafe_requests(struct ceph_mds_client *md
}
mutex_unlock(&mdsc->mutex);
ceph_put_mds_session(last_session);
- dout("%s done\n", __func__);
+ doutc(cl, "done\n");
}
void ceph_mdsc_sync(struct ceph_mds_client *mdsc)
{
+ struct ceph_client *cl = mdsc->fsc->client;
u64 want_tid, want_flush;
if (READ_ONCE(mdsc->fsc->mount_state) >= CEPH_MOUNT_SHUTDOWN)
return;
- dout("sync\n");
+ doutc(cl, "sync\n");
mutex_lock(&mdsc->mutex);
want_tid = mdsc->last_tid;
mutex_unlock(&mdsc->mutex);
@@ -5420,8 +5487,7 @@ void ceph_mdsc_sync(struct ceph_mds_client *mdsc)
}
spin_unlock(&mdsc->cap_dirty_lock);
- dout("sync want tid %lld flush_seq %lld\n",
- want_tid, want_flush);
+ doutc(cl, "sync want tid %lld flush_seq %lld\n", want_tid, want_flush);
flush_mdlog_and_wait_mdsc_unsafe_requests(mdsc, want_tid);
wait_caps_flush(mdsc, want_flush);
@@ -5443,11 +5509,12 @@ static bool done_closing_sessions(struct ceph_mds_client *mdsc, int skipped)
void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
{
struct ceph_options *opts = mdsc->fsc->client->options;
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mds_session *session;
int i;
int skipped = 0;
- dout("close_sessions\n");
+ doutc(cl, "begin\n");
/* close sessions */
mutex_lock(&mdsc->mutex);
@@ -5465,7 +5532,7 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
}
mutex_unlock(&mdsc->mutex);
- dout("waiting for sessions to close\n");
+ doutc(cl, "waiting for sessions to close\n");
wait_event_timeout(mdsc->session_close_wq,
done_closing_sessions(mdsc, skipped),
ceph_timeout_jiffies(opts->mount_timeout));
@@ -5493,7 +5560,7 @@ void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
cancel_work_sync(&mdsc->cap_reclaim_work);
cancel_delayed_work_sync(&mdsc->delayed_work); /* cancel timer */
- dout("stopped\n");
+ doutc(cl, "done\n");
}
void ceph_mdsc_force_umount(struct ceph_mds_client *mdsc)
@@ -5501,7 +5568,7 @@ void ceph_mdsc_force_umount(struct ceph_mds_client *mdsc)
struct ceph_mds_session *session;
int mds;
- dout("force umount\n");
+ doutc(mdsc->fsc->client, "force umount\n");
mutex_lock(&mdsc->mutex);
for (mds = 0; mds < mdsc->max_sessions; mds++) {
@@ -5532,7 +5599,7 @@ void ceph_mdsc_force_umount(struct ceph_mds_client *mdsc)
static void ceph_mdsc_stop(struct ceph_mds_client *mdsc)
{
- dout("stop\n");
+ doutc(mdsc->fsc->client, "stop\n");
/*
* Make sure the delayed work stopped before releasing
* the resources.
@@ -5553,7 +5620,7 @@ static void ceph_mdsc_stop(struct ceph_mds_client *mdsc)
void ceph_mdsc_destroy(struct ceph_fs_client *fsc)
{
struct ceph_mds_client *mdsc = fsc->mdsc;
- dout("mdsc_destroy %p\n", mdsc);
+ doutc(fsc->client, "%p\n", mdsc);
if (!mdsc)
return;
@@ -5567,12 +5634,13 @@ void ceph_mdsc_destroy(struct ceph_fs_client *fsc)
fsc->mdsc = NULL;
kfree(mdsc);
- dout("mdsc_destroy %p done\n", mdsc);
+ doutc(fsc->client, "%p done\n", mdsc);
}
void ceph_mdsc_handle_fsmap(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
{
struct ceph_fs_client *fsc = mdsc->fsc;
+ struct ceph_client *cl = fsc->client;
const char *mds_namespace = fsc->mount_options->mds_namespace;
void *p = msg->front.iov_base;
void *end = p + msg->front.iov_len;
@@ -5584,7 +5652,7 @@ void ceph_mdsc_handle_fsmap(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
ceph_decode_need(&p, end, sizeof(u32), bad);
epoch = ceph_decode_32(&p);
- dout("handle_fsmap epoch %u\n", epoch);
+ doutc(cl, "epoch %u\n", epoch);
/* struct_v, struct_cv, map_len, epoch, legacy_client_fscid */
ceph_decode_skip_n(&p, end, 2 + sizeof(u32) * 3, bad);
@@ -5629,7 +5697,8 @@ void ceph_mdsc_handle_fsmap(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
return;
bad:
- pr_err("error decoding fsmap %d. Shutting down mount.\n", err);
+ pr_err_client(cl, "error decoding fsmap %d. Shutting down mount.\n",
+ err);
ceph_umount_begin(mdsc->fsc->sb);
ceph_msg_dump(msg);
err_out:
@@ -5644,6 +5713,7 @@ void ceph_mdsc_handle_fsmap(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
*/
void ceph_mdsc_handle_mdsmap(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
{
+ struct ceph_client *cl = mdsc->fsc->client;
u32 epoch;
u32 maplen;
void *p = msg->front.iov_base;
@@ -5658,13 +5728,12 @@ void ceph_mdsc_handle_mdsmap(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
return;
epoch = ceph_decode_32(&p);
maplen = ceph_decode_32(&p);
- dout("handle_map epoch %u len %d\n", epoch, (int)maplen);
+ doutc(cl, "epoch %u len %d\n", epoch, (int)maplen);
/* do we need it? */
mutex_lock(&mdsc->mutex);
if (mdsc->mdsmap && epoch <= mdsc->mdsmap->m_epoch) {
- dout("handle_map epoch %u <= our %u\n",
- epoch, mdsc->mdsmap->m_epoch);
+ doutc(cl, "epoch %u <= our %u\n", epoch, mdsc->mdsmap->m_epoch);
mutex_unlock(&mdsc->mutex);
return;
}
@@ -5698,7 +5767,8 @@ void ceph_mdsc_handle_mdsmap(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
bad_unlock:
mutex_unlock(&mdsc->mutex);
bad:
- pr_err("error decoding mdsmap %d. Shutting down mount.\n", err);
+ pr_err_client(cl, "error decoding mdsmap %d. Shutting down mount.\n",
+ err);
ceph_umount_begin(mdsc->fsc->sb);
ceph_msg_dump(msg);
return;
@@ -5729,7 +5799,8 @@ static void mds_peer_reset(struct ceph_connection *con)
struct ceph_mds_session *s = con->private;
struct ceph_mds_client *mdsc = s->s_mdsc;
- pr_warn("mds%d closed our session\n", s->s_mds);
+ pr_warn_client(mdsc->fsc->client, "mds%d closed our session\n",
+ s->s_mds);
if (READ_ONCE(mdsc->fsc->mount_state) != CEPH_MOUNT_FENCE_IO)
send_mds_reconnect(mdsc, s);
}
@@ -5738,6 +5809,7 @@ static void mds_dispatch(struct ceph_connection *con, struct ceph_msg *msg)
{
struct ceph_mds_session *s = con->private;
struct ceph_mds_client *mdsc = s->s_mdsc;
+ struct ceph_client *cl = mdsc->fsc->client;
int type = le16_to_cpu(msg->hdr.type);
mutex_lock(&mdsc->mutex);
@@ -5777,8 +5849,8 @@ static void mds_dispatch(struct ceph_connection *con, struct ceph_msg *msg)
break;
default:
- pr_err("received unknown message type %d %s\n", type,
- ceph_msg_type_name(type));
+ pr_err_client(cl, "received unknown message type %d %s\n",
+ type, ceph_msg_type_name(type));
}
out:
ceph_msg_put(msg);
diff --git a/fs/ceph/mdsmap.c b/fs/ceph/mdsmap.c
index 66afb18df76b..a476d5e6d39f 100644
--- a/fs/ceph/mdsmap.c
+++ b/fs/ceph/mdsmap.c
@@ -11,6 +11,7 @@
#include <linux/ceph/messenger.h>
#include <linux/ceph/decode.h>
+#include "mds_client.h"
#include "super.h"
#define CEPH_MDS_IS_READY(i, ignore_laggy) \
@@ -117,6 +118,7 @@ static int __decode_and_drop_compat_set(void **p, void* end)
struct ceph_mdsmap *ceph_mdsmap_decode(struct ceph_mds_client *mdsc, void **p,
void *end, bool msgr2)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mdsmap *m;
const void *start = *p;
int i, j, n;
@@ -234,20 +236,18 @@ struct ceph_mdsmap *ceph_mdsmap_decode(struct ceph_mds_client *mdsc, void **p,
*p = info_end;
}
- dout("mdsmap_decode %d/%d %lld mds%d.%d %s %s%s\n",
- i+1, n, global_id, mds, inc,
- ceph_pr_addr(&addr),
- ceph_mds_state_name(state),
- laggy ? "(laggy)" : "");
+ doutc(cl, "%d/%d %lld mds%d.%d %s %s%s\n", i+1, n, global_id,
+ mds, inc, ceph_pr_addr(&addr),
+ ceph_mds_state_name(state), laggy ? "(laggy)" : "");
if (mds < 0 || mds >= m->possible_max_rank) {
- pr_warn("mdsmap_decode got incorrect mds(%d)\n", mds);
+ pr_warn_client(cl, "got incorrect mds(%d)\n", mds);
continue;
}
if (state <= 0) {
- dout("mdsmap_decode got incorrect state(%s)\n",
- ceph_mds_state_name(state));
+ doutc(cl, "got incorrect state(%s)\n",
+ ceph_mds_state_name(state));
continue;
}
@@ -387,16 +387,16 @@ struct ceph_mdsmap *ceph_mdsmap_decode(struct ceph_mds_client *mdsc, void **p,
ceph_decode_64_safe(p, end, m->m_max_xattr_size, bad_ext);
}
bad_ext:
- dout("mdsmap_decode m_enabled: %d, m_damaged: %d, m_num_laggy: %d\n",
- !!m->m_enabled, !!m->m_damaged, m->m_num_laggy);
+ doutc(cl, "m_enabled: %d, m_damaged: %d, m_num_laggy: %d\n",
+ !!m->m_enabled, !!m->m_damaged, m->m_num_laggy);
*p = end;
- dout("mdsmap_decode success epoch %u\n", m->m_epoch);
+ doutc(cl, "success epoch %u\n", m->m_epoch);
return m;
nomem:
err = -ENOMEM;
goto out_err;
corrupt:
- pr_err("corrupt mdsmap\n");
+ pr_err_client(cl, "corrupt mdsmap\n");
print_hex_dump(KERN_DEBUG, "mdsmap: ",
DUMP_PREFIX_OFFSET, 16, 1,
start, end - start, true);
diff --git a/fs/ceph/metric.c b/fs/ceph/metric.c
index 6d3584f16f9a..871c1090e520 100644
--- a/fs/ceph/metric.c
+++ b/fs/ceph/metric.c
@@ -31,6 +31,7 @@ static bool ceph_mdsc_send_metrics(struct ceph_mds_client *mdsc,
struct ceph_client_metric *m = &mdsc->metric;
u64 nr_caps = atomic64_read(&m->total_caps);
u32 header_len = sizeof(struct ceph_metric_header);
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_msg *msg;
s64 sum;
s32 items = 0;
@@ -51,8 +52,8 @@ static bool ceph_mdsc_send_metrics(struct ceph_mds_client *mdsc,
msg = ceph_msg_new(CEPH_MSG_CLIENT_METRICS, len, GFP_NOFS, true);
if (!msg) {
- pr_err("send metrics to mds%d, failed to allocate message\n",
- s->s_mds);
+ pr_err_client(cl, "to mds%d, failed to allocate message\n",
+ s->s_mds);
return false;
}
diff --git a/fs/ceph/quota.c b/fs/ceph/quota.c
index ca4932e6f71b..06ee397e0c3a 100644
--- a/fs/ceph/quota.c
+++ b/fs/ceph/quota.c
@@ -43,6 +43,7 @@ void ceph_handle_quota(struct ceph_mds_client *mdsc,
{
struct super_block *sb = mdsc->fsc->sb;
struct ceph_mds_quota *h = msg->front.iov_base;
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_vino vino;
struct inode *inode;
struct ceph_inode_info *ci;
@@ -51,8 +52,8 @@ void ceph_handle_quota(struct ceph_mds_client *mdsc,
return;
if (msg->front.iov_len < sizeof(*h)) {
- pr_err("%s corrupt message mds%d len %d\n", __func__,
- session->s_mds, (int)msg->front.iov_len);
+ pr_err_client(cl, "corrupt message mds%d len %d\n",
+ session->s_mds, (int)msg->front.iov_len);
ceph_msg_dump(msg);
goto out;
}
@@ -62,7 +63,7 @@ void ceph_handle_quota(struct ceph_mds_client *mdsc,
vino.snap = CEPH_NOSNAP;
inode = ceph_find_inode(sb, vino);
if (!inode) {
- pr_warn("Failed to find inode %llu\n", vino.ino);
+ pr_warn_client(cl, "failed to find inode %llx\n", vino.ino);
goto out;
}
ci = ceph_inode(inode);
@@ -85,6 +86,7 @@ find_quotarealm_inode(struct ceph_mds_client *mdsc, u64 ino)
{
struct ceph_quotarealm_inode *qri = NULL;
struct rb_node **node, *parent = NULL;
+ struct ceph_client *cl = mdsc->fsc->client;
mutex_lock(&mdsc->quotarealms_inodes_mutex);
node = &(mdsc->quotarealms_inodes.rb_node);
@@ -110,7 +112,7 @@ find_quotarealm_inode(struct ceph_mds_client *mdsc, u64 ino)
rb_link_node(&qri->node, parent, node);
rb_insert_color(&qri->node, &mdsc->quotarealms_inodes);
} else
- pr_warn("Failed to alloc quotarealms_inode\n");
+ pr_warn_client(cl, "Failed to alloc quotarealms_inode\n");
}
mutex_unlock(&mdsc->quotarealms_inodes_mutex);
@@ -129,6 +131,7 @@ static struct inode *lookup_quotarealm_inode(struct ceph_mds_client *mdsc,
struct super_block *sb,
struct ceph_snap_realm *realm)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_quotarealm_inode *qri;
struct inode *in;
@@ -161,8 +164,8 @@ static struct inode *lookup_quotarealm_inode(struct ceph_mds_client *mdsc,
}
if (IS_ERR(in)) {
- dout("Can't lookup inode %llx (err: %ld)\n",
- realm->ino, PTR_ERR(in));
+ doutc(cl, "Can't lookup inode %llx (err: %ld)\n", realm->ino,
+ PTR_ERR(in));
qri->timeout = jiffies + msecs_to_jiffies(60 * 1000); /* XXX */
} else {
qri->timeout = 0;
@@ -212,6 +215,7 @@ static int get_quota_realm(struct ceph_mds_client *mdsc, struct inode *inode,
enum quota_get_realm which_quota,
struct ceph_snap_realm **realmp, bool retry)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_inode_info *ci = NULL;
struct ceph_snap_realm *realm, *next;
struct inode *in;
@@ -227,8 +231,9 @@ static int get_quota_realm(struct ceph_mds_client *mdsc, struct inode *inode,
if (realm)
ceph_get_snap_realm(mdsc, realm);
else
- pr_err_ratelimited("get_quota_realm: ino (%llx.%llx) "
- "null i_snap_realm\n", ceph_vinop(inode));
+ pr_err_ratelimited_client(cl,
+ "%p %llx.%llx null i_snap_realm\n",
+ inode, ceph_vinop(inode));
while (realm) {
bool has_inode;
@@ -322,6 +327,7 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op,
loff_t delta)
{
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_inode_info *ci;
struct ceph_snap_realm *realm, *next;
struct inode *in;
@@ -337,8 +343,9 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op,
if (realm)
ceph_get_snap_realm(mdsc, realm);
else
- pr_err_ratelimited("check_quota_exceeded: ino (%llx.%llx) "
- "null i_snap_realm\n", ceph_vinop(inode));
+ pr_err_ratelimited_client(cl,
+ "%p %llx.%llx null i_snap_realm\n",
+ inode, ceph_vinop(inode));
while (realm) {
bool has_inode;
@@ -388,7 +395,7 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op,
break;
default:
/* Shouldn't happen */
- pr_warn("Invalid quota check op (%d)\n", op);
+ pr_warn_client(cl, "Invalid quota check op (%d)\n", op);
exceeded = true; /* Just break the loop */
}
iput(in);
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
index d0d3612f28f0..73c526954749 100644
--- a/fs/ceph/snap.c
+++ b/fs/ceph/snap.c
@@ -138,7 +138,7 @@ static struct ceph_snap_realm *ceph_create_snap_realm(
__insert_snap_realm(&mdsc->snap_realms, realm);
mdsc->num_snap_realms++;
- dout("%s %llx %p\n", __func__, realm->ino, realm);
+ doutc(mdsc->fsc->client, "%llx %p\n", realm->ino, realm);
return realm;
}
@@ -150,6 +150,7 @@ static struct ceph_snap_realm *ceph_create_snap_realm(
static struct ceph_snap_realm *__lookup_snap_realm(struct ceph_mds_client *mdsc,
u64 ino)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct rb_node *n = mdsc->snap_realms.rb_node;
struct ceph_snap_realm *r;
@@ -162,7 +163,7 @@ static struct ceph_snap_realm *__lookup_snap_realm(struct ceph_mds_client *mdsc,
else if (ino > r->ino)
n = n->rb_right;
else {
- dout("%s %llx %p\n", __func__, r->ino, r);
+ doutc(cl, "%llx %p\n", r->ino, r);
return r;
}
}
@@ -188,9 +189,10 @@ static void __put_snap_realm(struct ceph_mds_client *mdsc,
static void __destroy_snap_realm(struct ceph_mds_client *mdsc,
struct ceph_snap_realm *realm)
{
+ struct ceph_client *cl = mdsc->fsc->client;
lockdep_assert_held_write(&mdsc->snap_rwsem);
- dout("%s %p %llx\n", __func__, realm, realm->ino);
+ doutc(cl, "%p %llx\n", realm, realm->ino);
rb_erase(&realm->node, &mdsc->snap_realms);
mdsc->num_snap_realms--;
@@ -290,6 +292,7 @@ static int adjust_snap_realm_parent(struct ceph_mds_client *mdsc,
struct ceph_snap_realm *realm,
u64 parentino)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_snap_realm *parent;
lockdep_assert_held_write(&mdsc->snap_rwsem);
@@ -303,8 +306,8 @@ static int adjust_snap_realm_parent(struct ceph_mds_client *mdsc,
if (IS_ERR(parent))
return PTR_ERR(parent);
}
- dout("%s %llx %p: %llx %p -> %llx %p\n", __func__, realm->ino,
- realm, realm->parent_ino, realm->parent, parentino, parent);
+ doutc(cl, "%llx %p: %llx %p -> %llx %p\n", realm->ino, realm,
+ realm->parent_ino, realm->parent, parentino, parent);
if (realm->parent) {
list_del_init(&realm->child_item);
ceph_put_snap_realm(mdsc, realm->parent);
@@ -334,6 +337,7 @@ static int build_snap_context(struct ceph_mds_client *mdsc,
struct list_head *realm_queue,
struct list_head *dirty_realms)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_snap_realm *parent = realm->parent;
struct ceph_snap_context *snapc;
int err = 0;
@@ -361,10 +365,10 @@ static int build_snap_context(struct ceph_mds_client *mdsc,
realm->cached_context->seq == realm->seq &&
(!parent ||
realm->cached_context->seq >= parent->cached_context->seq)) {
- dout("%s %llx %p: %p seq %lld (%u snaps) (unchanged)\n",
- __func__, realm->ino, realm, realm->cached_context,
- realm->cached_context->seq,
- (unsigned int)realm->cached_context->num_snaps);
+ doutc(cl, "%llx %p: %p seq %lld (%u snaps) (unchanged)\n",
+ realm->ino, realm, realm->cached_context,
+ realm->cached_context->seq,
+ (unsigned int)realm->cached_context->num_snaps);
return 0;
}
@@ -401,8 +405,8 @@ static int build_snap_context(struct ceph_mds_client *mdsc,
sort(snapc->snaps, num, sizeof(u64), cmpu64_rev, NULL);
snapc->num_snaps = num;
- dout("%s %llx %p: %p seq %lld (%u snaps)\n", __func__, realm->ino,
- realm, snapc, snapc->seq, (unsigned int) snapc->num_snaps);
+ doutc(cl, "%llx %p: %p seq %lld (%u snaps)\n", realm->ino, realm,
+ snapc, snapc->seq, (unsigned int) snapc->num_snaps);
ceph_put_snap_context(realm->cached_context);
realm->cached_context = snapc;
@@ -419,7 +423,7 @@ static int build_snap_context(struct ceph_mds_client *mdsc,
ceph_put_snap_context(realm->cached_context);
realm->cached_context = NULL;
}
- pr_err("%s %llx %p fail %d\n", __func__, realm->ino, realm, err);
+ pr_err_client(cl, "%llx %p fail %d\n", realm->ino, realm, err);
return err;
}
@@ -430,6 +434,7 @@ static void rebuild_snap_realms(struct ceph_mds_client *mdsc,
struct ceph_snap_realm *realm,
struct list_head *dirty_realms)
{
+ struct ceph_client *cl = mdsc->fsc->client;
LIST_HEAD(realm_queue);
int last = 0;
bool skip = false;
@@ -455,8 +460,8 @@ static void rebuild_snap_realms(struct ceph_mds_client *mdsc,
last = build_snap_context(mdsc, _realm, &realm_queue,
dirty_realms);
- dout("%s %llx %p, %s\n", __func__, _realm->ino, _realm,
- last > 0 ? "is deferred" : !last ? "succeeded" : "failed");
+ doutc(cl, "%llx %p, %s\n", realm->ino, realm,
+ last > 0 ? "is deferred" : !last ? "succeeded" : "failed");
/* is any child in the list ? */
list_for_each_entry(child, &_realm->children, child_item) {
@@ -526,6 +531,7 @@ static void ceph_queue_cap_snap(struct ceph_inode_info *ci,
struct ceph_cap_snap **pcapsnap)
{
struct inode *inode = &ci->netfs.inode;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_snap_context *old_snapc, *new_snapc;
struct ceph_cap_snap *capsnap = *pcapsnap;
struct ceph_buffer *old_blob = NULL;
@@ -551,14 +557,14 @@ static void ceph_queue_cap_snap(struct ceph_inode_info *ci,
as no new writes are allowed to start when pending, so any
writes in progress now were started before the previous
cap_snap. lucky us. */
- dout("%s %p %llx.%llx already pending\n",
- __func__, inode, ceph_vinop(inode));
+ doutc(cl, "%p %llx.%llx already pending\n", inode,
+ ceph_vinop(inode));
goto update_snapc;
}
if (ci->i_wrbuffer_ref_head == 0 &&
!(dirty & (CEPH_CAP_ANY_EXCL|CEPH_CAP_FILE_WR))) {
- dout("%s %p %llx.%llx nothing dirty|writing\n",
- __func__, inode, ceph_vinop(inode));
+ doutc(cl, "%p %llx.%llx nothing dirty|writing\n", inode,
+ ceph_vinop(inode));
goto update_snapc;
}
@@ -578,15 +584,15 @@ static void ceph_queue_cap_snap(struct ceph_inode_info *ci,
} else {
if (!(used & CEPH_CAP_FILE_WR) &&
ci->i_wrbuffer_ref_head == 0) {
- dout("%s %p %llx.%llx no new_snap|dirty_page|writing\n",
- __func__, inode, ceph_vinop(inode));
+ doutc(cl, "%p %llx.%llx no new_snap|dirty_page|writing\n",
+ inode, ceph_vinop(inode));
goto update_snapc;
}
}
- dout("%s %p %llx.%llx cap_snap %p queuing under %p %s %s\n",
- __func__, inode, ceph_vinop(inode), capsnap, old_snapc,
- ceph_cap_string(dirty), capsnap->need_flush ? "" : "no_flush");
+ doutc(cl, "%p %llx.%llx cap_snap %p queuing under %p %s %s\n",
+ inode, ceph_vinop(inode), capsnap, old_snapc,
+ ceph_cap_string(dirty), capsnap->need_flush ? "" : "no_flush");
ihold(inode);
capsnap->follows = old_snapc->seq;
@@ -618,9 +624,9 @@ static void ceph_queue_cap_snap(struct ceph_inode_info *ci,
list_add_tail(&capsnap->ci_item, &ci->i_cap_snaps);
if (used & CEPH_CAP_FILE_WR) {
- dout("%s %p %llx.%llx cap_snap %p snapc %p seq %llu used WR,"
- " now pending\n", __func__, inode, ceph_vinop(inode),
- capsnap, old_snapc, old_snapc->seq);
+ doutc(cl, "%p %llx.%llx cap_snap %p snapc %p seq %llu used WR,"
+ " now pending\n", inode, ceph_vinop(inode), capsnap,
+ old_snapc, old_snapc->seq);
capsnap->writing = 1;
} else {
/* note mtime, size NOW. */
@@ -637,7 +643,7 @@ static void ceph_queue_cap_snap(struct ceph_inode_info *ci,
ci->i_head_snapc = NULL;
} else {
ci->i_head_snapc = ceph_get_snap_context(new_snapc);
- dout(" new snapc is %p\n", new_snapc);
+ doutc(cl, " new snapc is %p\n", new_snapc);
}
spin_unlock(&ci->i_ceph_lock);
@@ -658,6 +664,7 @@ int __ceph_finish_cap_snap(struct ceph_inode_info *ci,
{
struct inode *inode = &ci->netfs.inode;
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
+ struct ceph_client *cl = mdsc->fsc->client;
BUG_ON(capsnap->writing);
capsnap->size = i_size_read(inode);
@@ -670,11 +677,12 @@ int __ceph_finish_cap_snap(struct ceph_inode_info *ci,
capsnap->truncate_size = ci->i_truncate_size;
capsnap->truncate_seq = ci->i_truncate_seq;
if (capsnap->dirty_pages) {
- dout("%s %p %llx.%llx cap_snap %p snapc %p %llu %s s=%llu "
- "still has %d dirty pages\n", __func__, inode,
- ceph_vinop(inode), capsnap, capsnap->context,
- capsnap->context->seq, ceph_cap_string(capsnap->dirty),
- capsnap->size, capsnap->dirty_pages);
+ doutc(cl, "%p %llx.%llx cap_snap %p snapc %p %llu %s "
+ "s=%llu still has %d dirty pages\n", inode,
+ ceph_vinop(inode), capsnap, capsnap->context,
+ capsnap->context->seq,
+ ceph_cap_string(capsnap->dirty),
+ capsnap->size, capsnap->dirty_pages);
return 0;
}
@@ -683,20 +691,20 @@ int __ceph_finish_cap_snap(struct ceph_inode_info *ci,
* And trigger to flush the buffer immediately.
*/
if (ci->i_wrbuffer_ref) {
- dout("%s %p %llx.%llx cap_snap %p snapc %p %llu %s s=%llu "
- "used WRBUFFER, delaying\n", __func__, inode,
- ceph_vinop(inode), capsnap, capsnap->context,
- capsnap->context->seq, ceph_cap_string(capsnap->dirty),
- capsnap->size);
+ doutc(cl, "%p %llx.%llx cap_snap %p snapc %p %llu %s "
+ "s=%llu used WRBUFFER, delaying\n", inode,
+ ceph_vinop(inode), capsnap, capsnap->context,
+ capsnap->context->seq, ceph_cap_string(capsnap->dirty),
+ capsnap->size);
ceph_queue_writeback(inode);
return 0;
}
ci->i_ceph_flags |= CEPH_I_FLUSH_SNAPS;
- dout("%s %p %llx.%llx cap_snap %p snapc %p %llu %s s=%llu\n",
- __func__, inode, ceph_vinop(inode), capsnap, capsnap->context,
- capsnap->context->seq, ceph_cap_string(capsnap->dirty),
- capsnap->size);
+ doutc(cl, "%p %llx.%llx cap_snap %p snapc %p %llu %s s=%llu\n",
+ inode, ceph_vinop(inode), capsnap, capsnap->context,
+ capsnap->context->seq, ceph_cap_string(capsnap->dirty),
+ capsnap->size);
spin_lock(&mdsc->snap_flush_lock);
if (list_empty(&ci->i_snap_flush_item)) {
@@ -714,11 +722,12 @@ int __ceph_finish_cap_snap(struct ceph_inode_info *ci,
static void queue_realm_cap_snaps(struct ceph_mds_client *mdsc,
struct ceph_snap_realm *realm)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_inode_info *ci;
struct inode *lastinode = NULL;
struct ceph_cap_snap *capsnap = NULL;
- dout("%s %p %llx inode\n", __func__, realm, realm->ino);
+ doutc(cl, "%p %llx inode\n", realm, realm->ino);
spin_lock(&realm->inodes_with_caps_lock);
list_for_each_entry(ci, &realm->inodes_with_caps, i_snap_realm_item) {
@@ -737,8 +746,9 @@ static void queue_realm_cap_snaps(struct ceph_mds_client *mdsc,
if (!capsnap) {
capsnap = kmem_cache_zalloc(ceph_cap_snap_cachep, GFP_NOFS);
if (!capsnap) {
- pr_err("ENOMEM allocating ceph_cap_snap on %p\n",
- inode);
+ pr_err_client(cl,
+ "ENOMEM allocating ceph_cap_snap on %p\n",
+ inode);
return;
}
}
@@ -756,7 +766,7 @@ static void queue_realm_cap_snaps(struct ceph_mds_client *mdsc,
if (capsnap)
kmem_cache_free(ceph_cap_snap_cachep, capsnap);
- dout("%s %p %llx done\n", __func__, realm, realm->ino);
+ doutc(cl, "%p %llx done\n", realm, realm->ino);
}
/*
@@ -770,6 +780,7 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,
void *p, void *e, bool deletion,
struct ceph_snap_realm **realm_ret)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_mds_snap_realm *ri; /* encoded */
__le64 *snaps; /* encoded */
__le64 *prior_parent_snaps; /* encoded */
@@ -784,7 +795,7 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,
lockdep_assert_held_write(&mdsc->snap_rwsem);
- dout("%s deletion=%d\n", __func__, deletion);
+ doutc(cl, "deletion=%d\n", deletion);
more:
realm = NULL;
rebuild_snapcs = 0;
@@ -814,8 +825,8 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,
rebuild_snapcs += err;
if (le64_to_cpu(ri->seq) > realm->seq) {
- dout("%s updating %llx %p %lld -> %lld\n", __func__,
- realm->ino, realm, realm->seq, le64_to_cpu(ri->seq));
+ doutc(cl, "updating %llx %p %lld -> %lld\n", realm->ino,
+ realm, realm->seq, le64_to_cpu(ri->seq));
/* update realm parameters, snap lists */
realm->seq = le64_to_cpu(ri->seq);
realm->created = le64_to_cpu(ri->created);
@@ -838,16 +849,16 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,
rebuild_snapcs = 1;
} else if (!realm->cached_context) {
- dout("%s %llx %p seq %lld new\n", __func__,
- realm->ino, realm, realm->seq);
+ doutc(cl, "%llx %p seq %lld new\n", realm->ino, realm,
+ realm->seq);
rebuild_snapcs = 1;
} else {
- dout("%s %llx %p seq %lld unchanged\n", __func__,
- realm->ino, realm, realm->seq);
+ doutc(cl, "%llx %p seq %lld unchanged\n", realm->ino, realm,
+ realm->seq);
}
- dout("done with %llx %p, rebuild_snapcs=%d, %p %p\n", realm->ino,
- realm, rebuild_snapcs, p, e);
+ doutc(cl, "done with %llx %p, rebuild_snapcs=%d, %p %p\n", realm->ino,
+ realm, rebuild_snapcs, p, e);
/*
* this will always track the uppest parent realm from which
@@ -895,7 +906,7 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,
ceph_put_snap_realm(mdsc, realm);
if (first_realm)
ceph_put_snap_realm(mdsc, first_realm);
- pr_err("%s error %d\n", __func__, err);
+ pr_err_client(cl, "error %d\n", err);
/*
* When receiving a corrupted snap trace we don't know what
@@ -909,11 +920,12 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,
WRITE_ONCE(mdsc->fsc->mount_state, CEPH_MOUNT_FENCE_IO);
ret = ceph_monc_blocklist_add(&client->monc, &client->msgr.inst.addr);
if (ret)
- pr_err("%s failed to blocklist %s: %d\n", __func__,
- ceph_pr_addr(&client->msgr.inst.addr), ret);
+ pr_err_client(cl, "failed to blocklist %s: %d\n",
+ ceph_pr_addr(&client->msgr.inst.addr), ret);
- WARN(1, "%s: %s%sdo remount to continue%s",
- __func__, ret ? "" : ceph_pr_addr(&client->msgr.inst.addr),
+ WARN(1, "[client.%lld] %s %s%sdo remount to continue%s",
+ client->monc.auth->global_id, __func__,
+ ret ? "" : ceph_pr_addr(&client->msgr.inst.addr),
ret ? "" : " was blocklisted, ",
err == -EIO ? " after corrupted snaptrace is fixed" : "");
@@ -929,11 +941,12 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,
*/
static void flush_snaps(struct ceph_mds_client *mdsc)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_inode_info *ci;
struct inode *inode;
struct ceph_mds_session *session = NULL;
- dout("%s\n", __func__);
+ doutc(cl, "begin\n");
spin_lock(&mdsc->snap_flush_lock);
while (!list_empty(&mdsc->snap_flush_list)) {
ci = list_first_entry(&mdsc->snap_flush_list,
@@ -948,7 +961,7 @@ static void flush_snaps(struct ceph_mds_client *mdsc)
spin_unlock(&mdsc->snap_flush_lock);
ceph_put_mds_session(session);
- dout("%s done\n", __func__);
+ doutc(cl, "done\n");
}
/**
@@ -1004,6 +1017,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session,
struct ceph_msg *msg)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct super_block *sb = mdsc->fsc->sb;
int mds = session->s_mds;
u64 split;
@@ -1034,8 +1048,8 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
trace_len = le32_to_cpu(h->trace_len);
p += sizeof(*h);
- dout("%s from mds%d op %s split %llx tracelen %d\n", __func__,
- mds, ceph_snap_op_name(op), split, trace_len);
+ doutc(cl, "from mds%d op %s split %llx tracelen %d\n", mds,
+ ceph_snap_op_name(op), split, trace_len);
down_write(&mdsc->snap_rwsem);
locked_rwsem = 1;
@@ -1066,7 +1080,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
goto out;
}
- dout("splitting snap_realm %llx %p\n", realm->ino, realm);
+ doutc(cl, "splitting snap_realm %llx %p\n", realm->ino, realm);
for (i = 0; i < num_split_inos; i++) {
struct ceph_vino vino = {
.ino = le64_to_cpu(split_inos[i]),
@@ -1091,13 +1105,13 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
*/
if (ci->i_snap_realm->created >
le64_to_cpu(ri->created)) {
- dout(" leaving %p %llx.%llx in newer realm %llx %p\n",
- inode, ceph_vinop(inode), ci->i_snap_realm->ino,
- ci->i_snap_realm);
+ doutc(cl, " leaving %p %llx.%llx in newer realm %llx %p\n",
+ inode, ceph_vinop(inode), ci->i_snap_realm->ino,
+ ci->i_snap_realm);
goto skip_inode;
}
- dout(" will move %p %llx.%llx to split realm %llx %p\n",
- inode, ceph_vinop(inode), realm->ino, realm);
+ doutc(cl, " will move %p %llx.%llx to split realm %llx %p\n",
+ inode, ceph_vinop(inode), realm->ino, realm);
ceph_get_snap_realm(mdsc, realm);
ceph_change_snap_realm(inode, realm);
@@ -1158,7 +1172,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
return;
bad:
- pr_err("%s corrupt snap message from mds%d\n", __func__, mds);
+ pr_err_client(cl, "corrupt snap message from mds%d\n", mds);
ceph_msg_dump(msg);
out:
if (locked_rwsem)
@@ -1174,6 +1188,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
struct ceph_snapid_map* ceph_get_snapid_map(struct ceph_mds_client *mdsc,
u64 snap)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_snapid_map *sm, *exist;
struct rb_node **p, *parent;
int ret;
@@ -1196,8 +1211,8 @@ struct ceph_snapid_map* ceph_get_snapid_map(struct ceph_mds_client *mdsc,
}
spin_unlock(&mdsc->snapid_map_lock);
if (exist) {
- dout("%s found snapid map %llx -> %x\n", __func__,
- exist->snap, exist->dev);
+ doutc(cl, "found snapid map %llx -> %x\n", exist->snap,
+ exist->dev);
return exist;
}
@@ -1241,13 +1256,12 @@ struct ceph_snapid_map* ceph_get_snapid_map(struct ceph_mds_client *mdsc,
if (exist) {
free_anon_bdev(sm->dev);
kfree(sm);
- dout("%s found snapid map %llx -> %x\n", __func__,
- exist->snap, exist->dev);
+ doutc(cl, "found snapid map %llx -> %x\n", exist->snap,
+ exist->dev);
return exist;
}
- dout("%s create snapid map %llx -> %x\n", __func__,
- sm->snap, sm->dev);
+ doutc(cl, "create snapid map %llx -> %x\n", sm->snap, sm->dev);
return sm;
}
@@ -1272,6 +1286,7 @@ void ceph_put_snapid_map(struct ceph_mds_client* mdsc,
void ceph_trim_snapid_map(struct ceph_mds_client *mdsc)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_snapid_map *sm;
unsigned long now;
LIST_HEAD(to_free);
@@ -1293,7 +1308,7 @@ void ceph_trim_snapid_map(struct ceph_mds_client *mdsc)
while (!list_empty(&to_free)) {
sm = list_first_entry(&to_free, struct ceph_snapid_map, lru);
list_del(&sm->lru);
- dout("trim snapid map %llx -> %x\n", sm->snap, sm->dev);
+ doutc(cl, "trim snapid map %llx -> %x\n", sm->snap, sm->dev);
free_anon_bdev(sm->dev);
kfree(sm);
}
@@ -1301,6 +1316,7 @@ void ceph_trim_snapid_map(struct ceph_mds_client *mdsc)
void ceph_cleanup_snapid_map(struct ceph_mds_client *mdsc)
{
+ struct ceph_client *cl = mdsc->fsc->client;
struct ceph_snapid_map *sm;
struct rb_node *p;
LIST_HEAD(to_free);
@@ -1319,8 +1335,8 @@ void ceph_cleanup_snapid_map(struct ceph_mds_client *mdsc)
list_del(&sm->lru);
free_anon_bdev(sm->dev);
if (WARN_ON_ONCE(atomic_read(&sm->ref))) {
- pr_err("snapid map %llx -> %x still in use\n",
- sm->snap, sm->dev);
+ pr_err_client(cl, "snapid map %llx -> %x still in use\n",
+ sm->snap, sm->dev);
}
kfree(sm);
}
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index 84e855e8929b..e4298a6c7c41 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -46,9 +46,10 @@ static void ceph_put_super(struct super_block *s)
{
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(s);
- dout("put_super\n");
+ doutc(fsc->client, "begin\n");
ceph_fscrypt_free_dummy_policy(fsc);
ceph_mdsc_close_sessions(fsc->mdsc);
+ doutc(fsc->client, "done\n");
}
static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
@@ -59,13 +60,13 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
int i, err;
u64 data_pool;
+ doutc(fsc->client, "begin\n");
if (fsc->mdsc->mdsmap->m_num_data_pg_pools == 1) {
data_pool = fsc->mdsc->mdsmap->m_data_pg_pools[0];
} else {
data_pool = CEPH_NOPOOL;
}
- dout("statfs\n");
err = ceph_monc_do_statfs(monc, data_pool, &st);
if (err < 0)
return err;
@@ -113,24 +114,26 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
/* fold the fs_cluster_id into the upper bits */
buf->f_fsid.val[1] = monc->fs_cluster_id;
+ doutc(fsc->client, "done\n");
return 0;
}
static int ceph_sync_fs(struct super_block *sb, int wait)
{
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb);
+ struct ceph_client *cl = fsc->client;
if (!wait) {
- dout("sync_fs (non-blocking)\n");
+ doutc(cl, "(non-blocking)\n");
ceph_flush_dirty_caps(fsc->mdsc);
- dout("sync_fs (non-blocking) done\n");
+ doutc(cl, "(non-blocking) done\n");
return 0;
}
- dout("sync_fs (blocking)\n");
+ doutc(cl, "(blocking)\n");
ceph_osdc_sync(&fsc->client->osdc);
ceph_mdsc_sync(fsc->mdsc);
- dout("sync_fs (blocking) done\n");
+ doutc(cl, "(blocking) done\n");
return 0;
}
@@ -349,7 +352,7 @@ static int ceph_parse_source(struct fs_parameter *param, struct fs_context *fc)
char *dev_name = param->string, *dev_name_end;
int ret;
- dout("%s '%s'\n", __func__, dev_name);
+ dout("'%s'\n", dev_name);
if (!dev_name || !*dev_name)
return invalfc(fc, "Empty source");
@@ -421,7 +424,7 @@ static int ceph_parse_mount_param(struct fs_context *fc,
return ret;
token = fs_parse(fc, ceph_mount_parameters, param, &result);
- dout("%s fs_parse '%s' token %d\n", __func__, param->key, token);
+ dout("%s: fs_parse '%s' token %d\n",__func__, param->key, token);
if (token < 0)
return token;
@@ -891,7 +894,7 @@ static void flush_fs_workqueues(struct ceph_fs_client *fsc)
static void destroy_fs_client(struct ceph_fs_client *fsc)
{
- dout("destroy_fs_client %p\n", fsc);
+ doutc(fsc->client, "%p\n", fsc);
spin_lock(&ceph_fsc_lock);
list_del(&fsc->metric_wakeup);
@@ -906,7 +909,7 @@ static void destroy_fs_client(struct ceph_fs_client *fsc)
ceph_destroy_client(fsc->client);
kfree(fsc);
- dout("destroy_fs_client %p done\n", fsc);
+ dout("%s: %p done\n", __func__, fsc);
}
/*
@@ -1028,7 +1031,7 @@ void ceph_umount_begin(struct super_block *sb)
{
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb);
- dout("ceph_umount_begin - starting forced umount\n");
+ doutc(fsc->client, "starting forced umount\n");
if (!fsc)
return;
fsc->mount_state = CEPH_MOUNT_SHUTDOWN;
@@ -1056,13 +1059,14 @@ static struct dentry *open_root_dentry(struct ceph_fs_client *fsc,
const char *path,
unsigned long started)
{
+ struct ceph_client *cl = fsc->client;
struct ceph_mds_client *mdsc = fsc->mdsc;
struct ceph_mds_request *req = NULL;
int err;
struct dentry *root;
/* open dir */
- dout("open_root_inode opening '%s'\n", path);
+ doutc(cl, "opening '%s'\n", path);
req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, USE_ANY_MDS);
if (IS_ERR(req))
return ERR_CAST(req);
@@ -1082,13 +1086,13 @@ static struct dentry *open_root_dentry(struct ceph_fs_client *fsc,
if (err == 0) {
struct inode *inode = req->r_target_inode;
req->r_target_inode = NULL;
- dout("open_root_inode success\n");
+ doutc(cl, "success\n");
root = d_make_root(inode);
if (!root) {
root = ERR_PTR(-ENOMEM);
goto out;
}
- dout("open_root_inode success, root dentry is %p\n", root);
+ doutc(cl, "success, root dentry is %p\n", root);
} else {
root = ERR_PTR(err);
}
@@ -1147,11 +1151,12 @@ static int ceph_apply_test_dummy_encryption(struct super_block *sb,
static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc,
struct fs_context *fc)
{
+ struct ceph_client *cl = fsc->client;
int err;
unsigned long started = jiffies; /* note the start time */
struct dentry *root;
- dout("mount start %p\n", fsc);
+ doutc(cl, "mount start %p\n", fsc);
mutex_lock(&fsc->client->mount_mutex);
if (!fsc->sb->s_root) {
@@ -1174,7 +1179,7 @@ static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc,
if (err)
goto out;
- dout("mount opening path '%s'\n", path);
+ doutc(cl, "mount opening path '%s'\n", path);
ceph_fs_debugfs_init(fsc);
@@ -1189,7 +1194,7 @@ static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc,
}
fsc->mount_state = CEPH_MOUNT_MOUNTED;
- dout("mount success\n");
+ doutc(cl, "mount success\n");
mutex_unlock(&fsc->client->mount_mutex);
return root;
@@ -1202,9 +1207,10 @@ static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc,
static int ceph_set_super(struct super_block *s, struct fs_context *fc)
{
struct ceph_fs_client *fsc = s->s_fs_info;
+ struct ceph_client *cl = fsc->client;
int ret;
- dout("set_super %p\n", s);
+ doutc(cl, "%p\n", s);
s->s_maxbytes = MAX_LFS_FILESIZE;
@@ -1239,30 +1245,31 @@ static int ceph_compare_super(struct super_block *sb, struct fs_context *fc)
struct ceph_mount_options *fsopt = new->mount_options;
struct ceph_options *opt = new->client->options;
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb);
+ struct ceph_client *cl = fsc->client;
- dout("ceph_compare_super %p\n", sb);
+ doutc(cl, "%p\n", sb);
if (compare_mount_options(fsopt, opt, fsc)) {
- dout("monitor(s)/mount options don't match\n");
+ doutc(cl, "monitor(s)/mount options don't match\n");
return 0;
}
if ((opt->flags & CEPH_OPT_FSID) &&
ceph_fsid_compare(&opt->fsid, &fsc->client->fsid)) {
- dout("fsid doesn't match\n");
+ doutc(cl, "fsid doesn't match\n");
return 0;
}
if (fc->sb_flags != (sb->s_flags & ~SB_BORN)) {
- dout("flags differ\n");
+ doutc(cl, "flags differ\n");
return 0;
}
if (fsc->blocklisted && !ceph_test_mount_opt(fsc, CLEANRECOVER)) {
- dout("client is blocklisted (and CLEANRECOVER is not set)\n");
+ doutc(cl, "client is blocklisted (and CLEANRECOVER is not set)\n");
return 0;
}
if (fsc->mount_state == CEPH_MOUNT_SHUTDOWN) {
- dout("client has been forcibly unmounted\n");
+ doutc(cl, "client has been forcibly unmounted\n");
return 0;
}
@@ -1350,8 +1357,9 @@ static int ceph_get_tree(struct fs_context *fc)
err = PTR_ERR(res);
goto out_splat;
}
- dout("root %p inode %p ino %llx.%llx\n", res,
- d_inode(res), ceph_vinop(d_inode(res)));
+
+ doutc(fsc->client, "root %p inode %p ino %llx.%llx\n", res,
+ d_inode(res), ceph_vinop(d_inode(res)));
fc->root = fsc->sb->s_root;
return 0;
@@ -1409,7 +1417,8 @@ static int ceph_reconfigure_fc(struct fs_context *fc)
kfree(fsc->mount_options->mon_addr);
fsc->mount_options->mon_addr = fsopt->mon_addr;
fsopt->mon_addr = NULL;
- pr_notice("ceph: monitor addresses recorded, but not used for reconnection");
+ pr_notice_client(fsc->client,
+ "monitor addresses recorded, but not used for reconnection");
}
sync_filesystem(sb);
@@ -1529,10 +1538,11 @@ void ceph_dec_osd_stopping_blocker(struct ceph_mds_client *mdsc)
static void ceph_kill_sb(struct super_block *s)
{
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(s);
+ struct ceph_client *cl = fsc->client;
struct ceph_mds_client *mdsc = fsc->mdsc;
bool wait;
- dout("kill_sb %p\n", s);
+ doutc(cl, "%p\n", s);
ceph_mdsc_pre_umount(mdsc);
flush_fs_workqueues(fsc);
@@ -1563,9 +1573,9 @@ static void ceph_kill_sb(struct super_block *s)
&mdsc->stopping_waiter,
fsc->client->options->mount_timeout);
if (!timeleft) /* timed out */
- pr_warn("umount timed out, %ld\n", timeleft);
+ pr_warn_client(cl, "umount timed out, %ld\n", timeleft);
else if (timeleft < 0) /* killed */
- pr_warn("umount was killed, %ld\n", timeleft);
+ pr_warn_client(cl, "umount was killed, %ld\n", timeleft);
}
mdsc->stopping = CEPH_MDSC_STOPPING_FLUSHED;
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 5903e3fb6d75..e31ecbed609d 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -506,6 +506,12 @@ ceph_sb_to_mdsc(const struct super_block *sb)
return (struct ceph_mds_client *)ceph_sb_to_fs_client(sb)->mdsc;
}
+static inline struct ceph_client *
+ceph_inode_to_client(const struct inode *inode)
+{
+ return (struct ceph_client *)ceph_inode_to_fs_client(inode)->client;
+}
+
static inline struct ceph_vino
ceph_vino(const struct inode *inode)
{
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index 6fd6a652499e..a2f948d4aa6c 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -58,6 +58,7 @@ static ssize_t ceph_vxattrcb_layout(struct ceph_inode_info *ci, char *val,
size_t size)
{
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(ci->netfs.inode.i_sb);
+ struct ceph_client *cl = fsc->client;
struct ceph_osd_client *osdc = &fsc->client->osdc;
struct ceph_string *pool_ns;
s64 pool = ci->i_layout.pool_id;
@@ -69,7 +70,7 @@ static ssize_t ceph_vxattrcb_layout(struct ceph_inode_info *ci, char *val,
pool_ns = ceph_try_get_string(ci->i_layout.pool_ns);
- dout("ceph_vxattrcb_layout %p\n", &ci->netfs.inode);
+ doutc(cl, "%p\n", &ci->netfs.inode);
down_read(&osdc->lock);
pool_name = ceph_pg_pool_name_by_id(osdc->osdmap, pool);
if (pool_name) {
@@ -570,6 +571,8 @@ static int __set_xattr(struct ceph_inode_info *ci,
int flags, int update_xattr,
struct ceph_inode_xattr **newxattr)
{
+ struct inode *inode = &ci->netfs.inode;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct rb_node **p;
struct rb_node *parent = NULL;
struct ceph_inode_xattr *xattr = NULL;
@@ -626,7 +629,7 @@ static int __set_xattr(struct ceph_inode_info *ci,
xattr->should_free_name = update_xattr;
ci->i_xattrs.count++;
- dout("%s count=%d\n", __func__, ci->i_xattrs.count);
+ doutc(cl, "count=%d\n", ci->i_xattrs.count);
} else {
kfree(*newxattr);
*newxattr = NULL;
@@ -654,13 +657,13 @@ static int __set_xattr(struct ceph_inode_info *ci,
if (new) {
rb_link_node(&xattr->node, parent, p);
rb_insert_color(&xattr->node, &ci->i_xattrs.index);
- dout("%s p=%p\n", __func__, p);
+ doutc(cl, "p=%p\n", p);
}
- dout("%s added %llx.%llx xattr %p %.*s=%.*s%s\n", __func__,
- ceph_vinop(&ci->netfs.inode), xattr, name_len, name,
- min(val_len, MAX_XATTR_VAL_PRINT_LEN), val,
- val_len > MAX_XATTR_VAL_PRINT_LEN ? "..." : "");
+ doutc(cl, "added %p %llx.%llx xattr %p %.*s=%.*s%s\n", inode,
+ ceph_vinop(inode), xattr, name_len, name, min(val_len,
+ MAX_XATTR_VAL_PRINT_LEN), val,
+ val_len > MAX_XATTR_VAL_PRINT_LEN ? "..." : "");
return 0;
}
@@ -668,6 +671,7 @@ static int __set_xattr(struct ceph_inode_info *ci,
static struct ceph_inode_xattr *__get_xattr(struct ceph_inode_info *ci,
const char *name)
{
+ struct ceph_client *cl = ceph_inode_to_client(&ci->netfs.inode);
struct rb_node **p;
struct rb_node *parent = NULL;
struct ceph_inode_xattr *xattr = NULL;
@@ -688,13 +692,13 @@ static struct ceph_inode_xattr *__get_xattr(struct ceph_inode_info *ci,
else {
int len = min(xattr->val_len, MAX_XATTR_VAL_PRINT_LEN);
- dout("%s %s: found %.*s%s\n", __func__, name, len,
- xattr->val, xattr->val_len > len ? "..." : "");
+ doutc(cl, "%s found %.*s%s\n", name, len, xattr->val,
+ xattr->val_len > len ? "..." : "");
return xattr;
}
}
- dout("%s %s: not found\n", __func__, name);
+ doutc(cl, "%s not found\n", name);
return NULL;
}
@@ -735,19 +739,20 @@ static int __remove_xattr(struct ceph_inode_info *ci,
static char *__copy_xattr_names(struct ceph_inode_info *ci,
char *dest)
{
+ struct ceph_client *cl = ceph_inode_to_client(&ci->netfs.inode);
struct rb_node *p;
struct ceph_inode_xattr *xattr = NULL;
p = rb_first(&ci->i_xattrs.index);
- dout("__copy_xattr_names count=%d\n", ci->i_xattrs.count);
+ doutc(cl, "count=%d\n", ci->i_xattrs.count);
while (p) {
xattr = rb_entry(p, struct ceph_inode_xattr, node);
memcpy(dest, xattr->name, xattr->name_len);
dest[xattr->name_len] = '\0';
- dout("dest=%s %p (%s) (%d/%d)\n", dest, xattr, xattr->name,
- xattr->name_len, ci->i_xattrs.names_size);
+ doutc(cl, "dest=%s %p (%s) (%d/%d)\n", dest, xattr, xattr->name,
+ xattr->name_len, ci->i_xattrs.names_size);
dest += xattr->name_len + 1;
p = rb_next(p);
@@ -758,19 +763,19 @@ static char *__copy_xattr_names(struct ceph_inode_info *ci,
void __ceph_destroy_xattrs(struct ceph_inode_info *ci)
{
+ struct ceph_client *cl = ceph_inode_to_client(&ci->netfs.inode);
struct rb_node *p, *tmp;
struct ceph_inode_xattr *xattr = NULL;
p = rb_first(&ci->i_xattrs.index);
- dout("__ceph_destroy_xattrs p=%p\n", p);
+ doutc(cl, "p=%p\n", p);
while (p) {
xattr = rb_entry(p, struct ceph_inode_xattr, node);
tmp = p;
p = rb_next(tmp);
- dout("__ceph_destroy_xattrs next p=%p (%.*s)\n", p,
- xattr->name_len, xattr->name);
+ doutc(cl, "next p=%p (%.*s)\n", p, xattr->name_len, xattr->name);
rb_erase(tmp, &ci->i_xattrs.index);
__free_xattr(xattr);
@@ -787,6 +792,7 @@ static int __build_xattrs(struct inode *inode)
__releases(ci->i_ceph_lock)
__acquires(ci->i_ceph_lock)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
u32 namelen;
u32 numattr = 0;
void *p, *end;
@@ -798,8 +804,8 @@ static int __build_xattrs(struct inode *inode)
int err = 0;
int i;
- dout("__build_xattrs() len=%d\n",
- ci->i_xattrs.blob ? (int)ci->i_xattrs.blob->vec.iov_len : 0);
+ doutc(cl, "len=%d\n",
+ ci->i_xattrs.blob ? (int)ci->i_xattrs.blob->vec.iov_len : 0);
if (ci->i_xattrs.index_version >= ci->i_xattrs.version)
return 0; /* already built */
@@ -874,6 +880,8 @@ static int __build_xattrs(struct inode *inode)
static int __get_required_blob_size(struct ceph_inode_info *ci, int name_size,
int val_size)
{
+ struct ceph_client *cl = ceph_inode_to_client(&ci->netfs.inode);
+
/*
* 4 bytes for the length, and additional 4 bytes per each xattr name,
* 4 bytes per each value
@@ -881,9 +889,8 @@ static int __get_required_blob_size(struct ceph_inode_info *ci, int name_size,
int size = 4 + ci->i_xattrs.count*(4 + 4) +
ci->i_xattrs.names_size +
ci->i_xattrs.vals_size;
- dout("__get_required_blob_size c=%d names.size=%d vals.size=%d\n",
- ci->i_xattrs.count, ci->i_xattrs.names_size,
- ci->i_xattrs.vals_size);
+ doutc(cl, "c=%d names.size=%d vals.size=%d\n", ci->i_xattrs.count,
+ ci->i_xattrs.names_size, ci->i_xattrs.vals_size);
if (name_size)
size += 4 + 4 + name_size + val_size;
@@ -899,12 +906,14 @@ static int __get_required_blob_size(struct ceph_inode_info *ci, int name_size,
*/
struct ceph_buffer *__ceph_build_xattrs_blob(struct ceph_inode_info *ci)
{
+ struct inode *inode = &ci->netfs.inode;
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct rb_node *p;
struct ceph_inode_xattr *xattr = NULL;
struct ceph_buffer *old_blob = NULL;
void *dest;
- dout("__build_xattrs_blob %p\n", &ci->netfs.inode);
+ doutc(cl, "%p %llx.%llx\n", inode, ceph_vinop(inode));
if (ci->i_xattrs.dirty) {
int need = __get_required_blob_size(ci, 0, 0);
@@ -962,6 +971,7 @@ static inline int __get_request_mask(struct inode *in) {
ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value,
size_t size)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_inode_xattr *xattr;
struct ceph_vxattr *vxattr;
@@ -1000,8 +1010,9 @@ ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value,
req_mask = __get_request_mask(inode);
spin_lock(&ci->i_ceph_lock);
- dout("getxattr %p name '%s' ver=%lld index_ver=%lld\n", inode, name,
- ci->i_xattrs.version, ci->i_xattrs.index_version);
+ doutc(cl, "%p %llx.%llx name '%s' ver=%lld index_ver=%lld\n", inode,
+ ceph_vinop(inode), name, ci->i_xattrs.version,
+ ci->i_xattrs.index_version);
if (ci->i_xattrs.version == 0 ||
!((req_mask & CEPH_CAP_XATTR_SHARED) ||
@@ -1010,8 +1021,9 @@ ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value,
/* security module gets xattr while filling trace */
if (current->journal_info) {
- pr_warn_ratelimited("sync getxattr %p "
- "during filling trace\n", inode);
+ pr_warn_ratelimited_client(cl,
+ "sync %p %llx.%llx during filling trace\n",
+ inode, ceph_vinop(inode));
return -EBUSY;
}
@@ -1053,14 +1065,16 @@ ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value,
ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size)
{
struct inode *inode = d_inode(dentry);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
bool len_only = (size == 0);
u32 namelen;
int err;
spin_lock(&ci->i_ceph_lock);
- dout("listxattr %p ver=%lld index_ver=%lld\n", inode,
- ci->i_xattrs.version, ci->i_xattrs.index_version);
+ doutc(cl, "%p %llx.%llx ver=%lld index_ver=%lld\n", inode,
+ ceph_vinop(inode), ci->i_xattrs.version,
+ ci->i_xattrs.index_version);
if (ci->i_xattrs.version == 0 ||
!__ceph_caps_issued_mask_metric(ci, CEPH_CAP_XATTR_SHARED, 1)) {
@@ -1095,6 +1109,7 @@ static int ceph_sync_setxattr(struct inode *inode, const char *name,
const char *value, size_t size, int flags)
{
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(inode->i_sb);
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_mds_request *req;
struct ceph_mds_client *mdsc = fsc->mdsc;
@@ -1119,7 +1134,7 @@ static int ceph_sync_setxattr(struct inode *inode, const char *name,
flags |= CEPH_XATTR_REMOVE;
}
- dout("setxattr value size: %zu\n", size);
+ doutc(cl, "name %s value size %zu\n", name, size);
/* do request */
req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS);
@@ -1148,10 +1163,10 @@ static int ceph_sync_setxattr(struct inode *inode, const char *name,
req->r_num_caps = 1;
req->r_inode_drop = CEPH_CAP_XATTR_SHARED;
- dout("xattr.ver (before): %lld\n", ci->i_xattrs.version);
+ doutc(cl, "xattr.ver (before): %lld\n", ci->i_xattrs.version);
err = ceph_mdsc_do_request(mdsc, NULL, req);
ceph_mdsc_put_request(req);
- dout("xattr.ver (after): %lld\n", ci->i_xattrs.version);
+ doutc(cl, "xattr.ver (after): %lld\n", ci->i_xattrs.version);
out:
if (pagelist)
@@ -1162,6 +1177,7 @@ static int ceph_sync_setxattr(struct inode *inode, const char *name,
int __ceph_setxattr(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
+ struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_vxattr *vxattr;
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
@@ -1220,9 +1236,9 @@ int __ceph_setxattr(struct inode *inode, const char *name,
required_blob_size = __get_required_blob_size(ci, name_len, val_len);
if ((ci->i_xattrs.version == 0) || !(issued & CEPH_CAP_XATTR_EXCL) ||
(required_blob_size > mdsc->mdsmap->m_max_xattr_size)) {
- dout("%s do sync setxattr: version: %llu size: %d max: %llu\n",
- __func__, ci->i_xattrs.version, required_blob_size,
- mdsc->mdsmap->m_max_xattr_size);
+ doutc(cl, "sync version: %llu size: %d max: %llu\n",
+ ci->i_xattrs.version, required_blob_size,
+ mdsc->mdsmap->m_max_xattr_size);
goto do_sync;
}
@@ -1236,8 +1252,8 @@ int __ceph_setxattr(struct inode *inode, const char *name,
}
}
- dout("setxattr %p name '%s' issued %s\n", inode, name,
- ceph_cap_string(issued));
+ doutc(cl, "%p %llx.%llx name '%s' issued %s\n", inode,
+ ceph_vinop(inode), name, ceph_cap_string(issued));
__build_xattrs(inode);
if (!ci->i_xattrs.prealloc_blob ||
@@ -1246,7 +1262,8 @@ int __ceph_setxattr(struct inode *inode, const char *name,
spin_unlock(&ci->i_ceph_lock);
ceph_buffer_put(old_blob); /* Shouldn't be required */
- dout(" pre-allocating new blob size=%d\n", required_blob_size);
+ doutc(cl, " pre-allocating new blob size=%d\n",
+ required_blob_size);
blob = ceph_buffer_new(required_blob_size, GFP_NOFS);
if (!blob)
goto do_sync_unlocked;
@@ -1286,8 +1303,9 @@ int __ceph_setxattr(struct inode *inode, const char *name,
/* security module set xattr while filling trace */
if (current->journal_info) {
- pr_warn_ratelimited("sync setxattr %p "
- "during filling trace\n", inode);
+ pr_warn_ratelimited_client(cl,
+ "sync %p %llx.%llx during filling trace\n",
+ inode, ceph_vinop(inode));
err = -EBUSY;
} else {
err = ceph_sync_setxattr(inode, name, value, size, flags);
diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig
index f6dc961e6c2b..2f0ae58b31eb 100644
--- a/fs/erofs/Kconfig
+++ b/fs/erofs/Kconfig
@@ -100,6 +100,20 @@ config EROFS_FS_ZIP_LZMA
If unsure, say N.
+config EROFS_FS_ZIP_LZMA_DEFAULT_MAX_STREAMS
+ int "EROFS LZMA default maximum decompression streams"
+ depends on EROFS_FS_ZIP_LZMA
+ range 1 NR_CPUS
+ default 16
+ help
+ By default EROFS allocates one LZMA decompression stream per CPU.
+ Each stream can hold a dictionary of up to 8 MiB taken from the
+ mounted image, so on systems with many CPUs this can reserve a lot
+ of memory. This caps the default; the lzma_streams module parameter
+ still overrides it.
+
+ If unsure, keep the default of 16.
+
config EROFS_FS_ZIP_DEFLATE
bool "EROFS DEFLATE compressed data support"
depends on EROFS_FS_ZIP
diff --git a/fs/erofs/decompressor_lzma.c b/fs/erofs/decompressor_lzma.c
index ba4ec73f4aae..613fe99cf629 100644
--- a/fs/erofs/decompressor_lzma.c
+++ b/fs/erofs/decompressor_lzma.c
@@ -53,7 +53,8 @@ int __init z_erofs_lzma_init(void)
/* by default, use # of possible CPUs instead */
if (!z_erofs_lzma_nstrms)
- z_erofs_lzma_nstrms = num_possible_cpus();
+ z_erofs_lzma_nstrms = min_t(unsigned int, num_possible_cpus(),
+ CONFIG_EROFS_FS_ZIP_LZMA_DEFAULT_MAX_STREAMS);
for (i = 0; i < z_erofs_lzma_nstrms; ++i) {
struct z_erofs_lzma *strm = kzalloc(sizeof(*strm), GFP_KERNEL);
diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c
index 91f4e50af1e9..877b4ad03fe9 100644
--- a/fs/smb/client/cifssmb.c
+++ b/fs/smb/client/cifssmb.c
@@ -1416,8 +1416,10 @@ CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
/* tcon and ses pointer are checked in smb_init */
- if (tcon->ses->server == NULL)
+ if (!tcon->ses->server) {
+ cifs_small_buf_release(pSMB);
return -ECONNABORTED;
+ }
pSMB->AndXCommand = 0xFF; /* none */
pSMB->Fid = netfid;
@@ -1529,8 +1531,10 @@ CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
/* tcon and ses pointer are checked in smb_init */
- if (tcon->ses->server == NULL)
+ if (!tcon->ses->server) {
+ cifs_buf_release(pSMB);
return -ECONNABORTED;
+ }
pSMB->AndXCommand = 0xFF; /* none */
pSMB->Fid = netfid;
@@ -1780,8 +1784,10 @@ CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
/* tcon and ses pointer are checked in smb_init */
- if (tcon->ses->server == NULL)
+ if (!tcon->ses->server) {
+ cifs_small_buf_release(pSMB);
return -ECONNABORTED;
+ }
pSMB->AndXCommand = 0xFF; /* none */
pSMB->Fid = netfid;
diff --git a/fs/smb/server/vfs_cache.c b/fs/smb/server/vfs_cache.c
index d15641007d4e..a15c42724849 100644
--- a/fs/smb/server/vfs_cache.c
+++ b/fs/smb/server/vfs_cache.c
@@ -487,6 +487,7 @@ int ksmbd_close_fd(struct ksmbd_work *work, u64 id)
{
struct ksmbd_file *fp;
struct ksmbd_file_table *ft;
+ bool closed = false;
if (!has_file_id(id))
return 0;
@@ -501,6 +502,9 @@ int ksmbd_close_fd(struct ksmbd_work *work, u64 id)
fp = NULL;
else {
fp->f_state = FP_CLOSED;
+ idr_remove(ft->idr, id);
+ fp->volatile_id = KSMBD_NO_FID;
+ closed = true;
if (!atomic_dec_and_test(&fp->refcount))
fp = NULL;
}
@@ -508,7 +512,7 @@ int ksmbd_close_fd(struct ksmbd_work *work, u64 id)
write_unlock(&ft->lock);
if (!fp)
- return -EINVAL;
+ return closed ? 0 : -EINVAL;
__put_fd_final(work, fp);
return 0;
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index 375737fd6c36..7bccce637aa8 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -246,8 +246,6 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper);
-struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper);
-void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper);
void drm_fb_helper_unregister_info(struct drm_fb_helper *fb_helper);
void drm_fb_helper_fill_info(struct fb_info *info,
struct drm_fb_helper *fb_helper,
@@ -330,16 +328,6 @@ drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
return 0;
}
-static inline struct fb_info *
-drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper)
-{
- return NULL;
-}
-
-static inline void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper)
-{
-}
-
static inline void drm_fb_helper_unregister_info(struct drm_fb_helper *fb_helper)
{
}
diff --git a/include/linux/can/core.h b/include/linux/can/core.h
index 5fb8d0e3f9c1..3287232e3cad 100644
--- a/include/linux/can/core.h
+++ b/include/linux/can/core.h
@@ -58,6 +58,7 @@ extern void can_rx_unregister(struct net *net, struct net_device *dev,
void *data);
extern int can_send(struct sk_buff *skb, int loop);
+void can_set_skb_uid(struct sk_buff *skb);
void can_sock_destruct(struct sock *sk);
#endif /* !_CAN_CORE_H */
diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
index 1abc25a8d144..869ea574a40a 100644
--- a/include/linux/can/skb.h
+++ b/include/linux/can/skb.h
@@ -49,13 +49,11 @@ bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb);
/**
* struct can_skb_priv - private additional data inside CAN sk_buffs
* @ifindex: ifindex of the first interface the CAN frame appeared on
- * @skbcnt: atomic counter to have an unique id together with skb pointer
* @frame_len: length of CAN frame in data link layer
* @cf: align to the following CAN frame at skb->data
*/
struct can_skb_priv {
int ifindex;
- int skbcnt;
unsigned int frame_len;
struct can_frame cf[];
};
diff --git a/include/linux/ceph/ceph_debug.h b/include/linux/ceph/ceph_debug.h
index d5a5da838caf..11a92a946016 100644
--- a/include/linux/ceph/ceph_debug.h
+++ b/include/linux/ceph/ceph_debug.h
@@ -19,12 +19,25 @@
pr_debug("%.*s %12.12s:%-4d : " fmt, \
8 - (int)sizeof(KBUILD_MODNAME), " ", \
kbasename(__FILE__), __LINE__, ##__VA_ARGS__)
+# define doutc(client, fmt, ...) \
+ pr_debug("%.*s %12.12s:%-4d : [%pU %llu] " fmt, \
+ 8 - (int)sizeof(KBUILD_MODNAME), " ", \
+ kbasename(__FILE__), __LINE__, \
+ &client->fsid, client->monc.auth->global_id, \
+ ##__VA_ARGS__)
# else
/* faux printk call just to see any compiler warnings. */
# define dout(fmt, ...) do { \
if (0) \
printk(KERN_DEBUG fmt, ##__VA_ARGS__); \
} while (0)
+# define doutc(client, fmt, ...) do { \
+ if (0) \
+ printk(KERN_DEBUG "[%pU %llu] " fmt, \
+ &client->fsid, \
+ client->monc.auth->global_id, \
+ ##__VA_ARGS__); \
+ } while (0)
# endif
#else
@@ -33,7 +46,32 @@
* or, just wrap pr_debug
*/
# define dout(fmt, ...) pr_debug(" " fmt, ##__VA_ARGS__)
+# define doutc(client, fmt, ...) \
+ pr_debug(" [%pU %llu] %s: " fmt, &client->fsid, \
+ client->monc.auth->global_id, __func__, ##__VA_ARGS__)
#endif
+#define pr_notice_client(client, fmt, ...) \
+ pr_notice("[%pU %llu]: " fmt, &client->fsid, \
+ client->monc.auth->global_id, ##__VA_ARGS__)
+#define pr_info_client(client, fmt, ...) \
+ pr_info("[%pU %llu]: " fmt, &client->fsid, \
+ client->monc.auth->global_id, ##__VA_ARGS__)
+#define pr_warn_client(client, fmt, ...) \
+ pr_warn("[%pU %llu]: " fmt, &client->fsid, \
+ client->monc.auth->global_id, ##__VA_ARGS__)
+#define pr_warn_once_client(client, fmt, ...) \
+ pr_warn_once("[%pU %llu]: " fmt, &client->fsid, \
+ client->monc.auth->global_id, ##__VA_ARGS__)
+#define pr_err_client(client, fmt, ...) \
+ pr_err("[%pU %llu]: " fmt, &client->fsid, \
+ client->monc.auth->global_id, ##__VA_ARGS__)
+#define pr_warn_ratelimited_client(client, fmt, ...) \
+ pr_warn_ratelimited("[%pU %llu]: " fmt, &client->fsid, \
+ client->monc.auth->global_id, ##__VA_ARGS__)
+#define pr_err_ratelimited_client(client, fmt, ...) \
+ pr_err_ratelimited("[%pU %llu]: " fmt, &client->fsid, \
+ client->monc.auth->global_id, ##__VA_ARGS__)
+
#endif
diff --git a/include/linux/dma/qcom_bam_dma.h b/include/linux/dma/qcom_bam_dma.h
index 68fc0e643b1b..d9d07a9ab313 100644
--- a/include/linux/dma/qcom_bam_dma.h
+++ b/include/linux/dma/qcom_bam_dma.h
@@ -13,9 +13,12 @@
* supported by BAM DMA Engine.
*
* @cmd_and_addr - upper 8 bits command and lower 24 bits register address.
- * @data - for write command: content to be written into peripheral register.
- * for read command: dest addr to write peripheral register value.
- * @mask - register mask.
+ * @data - For write command: content to be written into peripheral register.
+ * For read command: lower 32 bits of destination address.
+ * @mask - For write command: register write mask.
+ * For read command on BAM v1.6.0+: upper 4 bits of destination address.
+ * For read command on BAM < v1.6.0: ignored by hardware.
+ * Setting to 0 ensures 32-bit addressing compatibility.
* @reserved - for future usage.
*
*/
@@ -42,6 +45,10 @@ enum bam_command_type {
* @addr: target address
* @cmd: BAM command
* @data: actual data for write and dest addr for read in le32
+ *
+ * For BAM v1.6.0+, the mask field behavior depends on command type:
+ * - Write commands: mask = write mask (typically 0xffffffff)
+ * - Read commands: mask = upper 4 bits of destination address (0 for 32-bit)
*/
static inline void
bam_prep_ce_le32(struct bam_cmd_element *bam_ce, u32 addr,
@@ -50,7 +57,11 @@ bam_prep_ce_le32(struct bam_cmd_element *bam_ce, u32 addr,
bam_ce->cmd_and_addr =
cpu_to_le32((addr & 0xffffff) | ((cmd & 0xff) << 24));
bam_ce->data = data;
- bam_ce->mask = cpu_to_le32(0xffffffff);
+ if (cmd == BAM_READ_COMMAND)
+ bam_ce->mask = cpu_to_le32(0x0); /* 32-bit addressing */
+ else
+ bam_ce->mask = cpu_to_le32(0xffffffff); /* Write mask */
+ bam_ce->reserved = 0;
}
/*
@@ -60,7 +71,7 @@ bam_prep_ce_le32(struct bam_cmd_element *bam_ce, u32 addr,
* @bam_ce: BAM command element
* @addr: target address
* @cmd: BAM command
- * @data: actual data for write and dest addr for read
+ * @data: actual data for write and destination address for read
*/
static inline void
bam_prep_ce(struct bam_cmd_element *bam_ce, u32 addr,
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 285d709cbbde..ed2dbec700f5 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -360,7 +360,7 @@ enum {
/* This should match the actual table size of
* ata_eh_cmd_timeout_table in libata-eh.c.
*/
- ATA_EH_CMD_TIMEOUT_TABLE_SIZE = 8,
+ ATA_EH_CMD_TIMEOUT_TABLE_SIZE = 9,
/* Horkage types. May be set by libata or controller on drives
(some horkage may be drive/controller pair dependent */
diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h
index 7fada7a714fe..3a09426aff5e 100644
--- a/include/linux/mmc/sdio_ids.h
+++ b/include/linux/mmc/sdio_ids.h
@@ -76,7 +76,7 @@
#define SDIO_DEVICE_ID_BROADCOM_43430 0xa9a6
#define SDIO_DEVICE_ID_BROADCOM_43439 0xa9af
#define SDIO_DEVICE_ID_BROADCOM_43455 0xa9bf
-#define SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752 0xaae8
+#define SDIO_DEVICE_ID_BROADCOM_43752 0xaae8
#define SDIO_VENDOR_ID_CYPRESS 0x04b4
#define SDIO_DEVICE_ID_BROADCOM_CYPRESS_43439 0xbd3d
diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h
index dbc614dfe0d5..aafa0c04f917 100644
--- a/include/linux/netfilter/nf_conntrack_sip.h
+++ b/include/linux/netfilter/nf_conntrack_sip.h
@@ -115,7 +115,7 @@ struct nf_nat_sip_hooks {
unsigned int *datalen);
void (*seq_adjust)(struct sk_buff *skb,
- unsigned int protoff, s16 off);
+ unsigned int protoff, s32 off);
unsigned int (*expect)(struct sk_buff *skb,
unsigned int protoff,
diff --git a/include/linux/sched.h b/include/linux/sched.h
index fad3aad97c7b..c5e90874096e 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -878,6 +878,7 @@ struct task_struct {
struct mm_struct *mm;
struct mm_struct *active_mm;
+ struct address_space *faults_disabled_mapping;
int exit_state;
int exit_code;
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 698a71422a14..ef84ac08e6c9 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -182,7 +182,7 @@ struct ctl_table_header {
struct rcu_head rcu;
};
struct completion *unregistering;
- struct ctl_table *ctl_table_arg;
+ const struct ctl_table *ctl_table_arg;
struct ctl_table_root *root;
struct ctl_table_set *set;
struct ctl_dir *parent;
diff --git a/include/linux/thunderbolt.h b/include/linux/thunderbolt.h
index 02333f47c994..d95e69c1ac63 100644
--- a/include/linux/thunderbolt.h
+++ b/include/linux/thunderbolt.h
@@ -203,6 +203,8 @@ enum tb_link_width {
* @link_width: Width of the downstream facing link
* @link_usb4: Downstream link is USB4
* @is_unplugged: The XDomain is unplugged
+ * @removing: Set by tb_xdomain_remove() under @lock to prevent
+ * concurrent delayed work queueing
* @needs_uuid: If the XDomain does not have @remote_uuid it will be
* queried first
* @service_ids: Used to generate IDs for the services
@@ -251,6 +253,7 @@ struct tb_xdomain {
enum tb_link_width link_width;
bool link_usb4;
bool is_unplugged;
+ bool removing;
bool needs_uuid;
struct ida service_ids;
struct ida in_hopids;
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index 9bd326d31181..54a2d9620ed5 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -310,7 +310,9 @@ void v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier);
*
* @sd: pointer to &struct v4l2_subdev
*/
-int v4l2_async_register_subdev(struct v4l2_subdev *sd);
+#define v4l2_async_register_subdev(sd) \
+ __v4l2_async_register_subdev(sd, THIS_MODULE)
+int __v4l2_async_register_subdev(struct v4l2_subdev *sd, struct module *module);
/**
* v4l2_async_register_subdev_sensor - registers a sensor sub-device to the
@@ -331,8 +333,10 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd);
* An error is returned if the module is no longer loaded on any attempts
* to register it.
*/
+#define v4l2_async_register_subdev_sensor(sd) \
+ __v4l2_async_register_subdev_sensor(sd, THIS_MODULE)
int __must_check
-v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd);
+__v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd, struct module *module);
/**
* v4l2_async_unregister_subdev - unregisters a sub-device to the asynchronous
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 08b90d33acdc..6935ec09af24 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -24,7 +24,9 @@
#include <linux/netfilter.h> /* for union nf_inet_addr */
#include <linux/ip.h>
#include <linux/ipv6.h> /* for struct ipv6hdr */
+#include <net/route.h>
#include <net/ipv6.h>
+#include <net/ip6_fib.h>
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
#include <net/netfilter/nf_conntrack.h>
#endif
@@ -1624,8 +1626,8 @@ int ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
int ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
int ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp, int offset,
- unsigned int hooknum, struct ip_vs_iphdr *iph);
+ struct ip_vs_protocol *pp, unsigned int toff,
+ unsigned int hooknum, struct ip_vs_iphdr *ciph);
void ip_vs_dest_dst_rcu_free(struct rcu_head *head);
#ifdef CONFIG_IP_VS_IPV6
@@ -1638,8 +1640,8 @@ int ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
int ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
int ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp, int offset,
- unsigned int hooknum, struct ip_vs_iphdr *iph);
+ struct ip_vs_protocol *pp, unsigned int toff,
+ unsigned int hooknum, struct ip_vs_iphdr *ciph);
#endif
#ifdef CONFIG_SYSCTL
@@ -1704,15 +1706,15 @@ static inline char ip_vs_fwd_tag(struct ip_vs_conn *cp)
}
void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
- struct ip_vs_conn *cp, int dir);
+ struct ip_vs_conn *cp, int dir, unsigned int toff,
+ bool has_ports);
#ifdef CONFIG_IP_VS_IPV6
void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp,
- struct ip_vs_conn *cp, int dir);
+ struct ip_vs_conn *cp, int dir, unsigned int toff,
+ bool has_ports, struct ip_vs_iphdr *ciph);
#endif
-__sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset);
-
static inline __wsum ip_vs_check_diff4(__be32 old, __be32 new, __wsum oldsum)
{
__be32 diff[2] = { ~old, new };
@@ -1738,6 +1740,33 @@ static inline __wsum ip_vs_check_diff2(__be16 old, __be16 new, __wsum oldsum)
return csum_partial(diff, sizeof(diff), oldsum);
}
+static inline bool ip_vs_checksum_needed(struct sk_buff *skb, int af)
+{
+ /* Checksum unnecessary or already validated? */
+ if (skb_csum_unnecessary(skb))
+ return false;
+ /* LOCAL_OUT ? */
+ if (!skb->dev || skb->dev->flags & IFF_LOOPBACK)
+ return false;
+ /* !LOCAL_IN (FORWARD) ? */
+ if (af == AF_INET6) {
+ if (!(dst_rt6_info(skb_dst(skb))->rt6i_flags & RTF_LOCAL))
+ return false;
+ } else {
+ if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL))
+ return false;
+ }
+ return true;
+}
+
+static inline bool ip_vs_checksum_common_check(struct sk_buff *skb,
+ int offset, int proto, int af)
+{
+ if (!ip_vs_checksum_needed(skb, af))
+ return true;
+ return !nf_checksum(skb, NF_INET_LOCAL_IN, offset, proto, af);
+}
+
/* Forget current conntrack (unconfirmed) and attach notrack entry */
static inline void ip_vs_notrack(struct sk_buff *skb)
{
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index d775906a65c7..9ada7451fd2a 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -476,11 +476,15 @@ static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
static inline int neigh_hh_bridge(struct hh_cache *hh, struct sk_buff *skb)
{
- unsigned int seq, hh_alen;
+ unsigned int seq, hh_alen = HH_DATA_ALIGN(ETH_HLEN);
+ int err;
+
+ err = skb_cow_head(skb, hh_alen);
+ if (err)
+ return err;
do {
seq = read_seqbegin(&hh->hh_lock);
- hh_alen = HH_DATA_ALIGN(ETH_HLEN);
memcpy(skb->data - hh_alen, hh->hh_data, ETH_ALEN + hh_alen - ETH_HLEN);
} while (read_seqretry(&hh->hh_lock, seq));
return 0;
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
index e9a8350e7ccf..80f50fd0f7ad 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -45,9 +45,12 @@ struct nf_conntrack_expect {
void (*expectfn)(struct nf_conn *new,
struct nf_conntrack_expect *this);
- /* Helper to assign to new connection */
+ /* Helper that created this expectation */
struct nf_conntrack_helper __rcu *helper;
+ /* Helper to assign to new connection */
+ struct nf_conntrack_helper __rcu *assign_helper;
+
/* The conntrack of the master connection */
struct nf_conn *master;
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index aac4e1c54300..4056d2272487 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -302,11 +302,13 @@ struct nft_set_elem {
*
* @NFT_ITER_READ: read-only iteration over set elements
* @NFT_ITER_UPDATE: iteration under mutex to update set element state
+ * @NFT_ITER_UPDATE_CLONE: clone set before iteration under mutex to update element
*/
enum nft_iter_type {
NFT_ITER_UNSPEC,
NFT_ITER_READ,
NFT_ITER_UPDATE,
+ NFT_ITER_UPDATE_CLONE,
};
struct nft_set;
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 8a43534eea5c..367b06fe5fcb 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -678,7 +678,6 @@ extern int sas_register_ha(struct sas_ha_struct *);
extern int sas_unregister_ha(struct sas_ha_struct *);
extern void sas_prep_resume_ha(struct sas_ha_struct *sas_ha);
extern void sas_resume_ha(struct sas_ha_struct *sas_ha);
-extern void sas_resume_ha_no_sync(struct sas_ha_struct *sas_ha);
extern void sas_suspend_ha(struct sas_ha_struct *sas_ha);
int sas_set_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates);
diff --git a/init/init_task.c b/init/init_task.c
index fd9e27185e23..9b363c986f82 100644
--- a/init/init_task.c
+++ b/init/init_task.c
@@ -85,6 +85,7 @@ struct task_struct init_task
.nr_cpus_allowed= NR_CPUS,
.mm = NULL,
.active_mm = &init_mm,
+ .faults_disabled_mapping = NULL,
.restart_block = {
.fn = do_no_restart_syscall,
},
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
index 22b12a482ba9..becf66235cb0 100644
--- a/ipc/ipc_sysctl.c
+++ b/ipc/ipc_sysctl.c
@@ -306,7 +306,7 @@ bool setup_ipc_sysctls(struct ipc_namespace *ns)
void retire_ipc_sysctls(struct ipc_namespace *ns)
{
- struct ctl_table *tbl;
+ const struct ctl_table *tbl;
tbl = ns->ipc_sysctls->ctl_table_arg;
unregister_sysctl_table(ns->ipc_sysctls);
diff --git a/ipc/mq_sysctl.c b/ipc/mq_sysctl.c
index 6bb1c5397c69..42bce339ca97 100644
--- a/ipc/mq_sysctl.c
+++ b/ipc/mq_sysctl.c
@@ -159,7 +159,7 @@ bool setup_mq_sysctls(struct ipc_namespace *ns)
void retire_mq_sysctls(struct ipc_namespace *ns)
{
- struct ctl_table *tbl;
+ const struct ctl_table *tbl;
tbl = ns->mq_sysctls->ctl_table_arg;
unregister_sysctl_table(ns->mq_sysctls);
diff --git a/kernel/audit.c b/kernel/audit.c
index aa450ea116f1..908fd188bf62 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -2074,7 +2074,8 @@ void audit_log_n_hex(struct audit_buffer *ab, const unsigned char *buf,
void audit_log_n_string(struct audit_buffer *ab, const char *string,
size_t slen)
{
- int avail, new_len;
+ int avail;
+ size_t new_len;
unsigned char *ptr;
struct sk_buff *skb;
@@ -2084,7 +2085,13 @@ void audit_log_n_string(struct audit_buffer *ab, const char *string,
BUG_ON(!ab->skb);
skb = ab->skb;
avail = skb_tailroom(skb);
- new_len = slen + 3; /* enclosing quotes + null terminator */
+
+ /* enclosing quotes + null terminator */
+ if (check_add_overflow(slen, 3, &new_len)) {
+ audit_log_format(ab, "?");
+ return;
+ }
+
if (new_len > avail) {
avail = audit_expand(ab, new_len);
if (!avail)
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 3c4fd93254b5..538f5c640f7c 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1047,6 +1047,10 @@ int audit_del_rule(struct audit_entry *entry)
goto out;
}
+ list_del_rcu(&e->list);
+ list_del(&e->rule.list);
+ synchronize_rcu();
+
if (e->rule.watch)
audit_remove_watch_rule(&e->rule);
@@ -1064,8 +1068,6 @@ int audit_del_rule(struct audit_entry *entry)
audit_signals--;
#endif
- list_del_rcu(&e->list);
- list_del(&e->rule.list);
call_rcu(&e->rcu, audit_free_rule_rcu);
out:
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 9dc45aa43000..9588344ef8f7 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -3373,8 +3373,8 @@ static void trace_module_add_events(struct module *mod)
end = mod->trace_events + mod->num_trace_events;
for_each_event(call, start, end) {
- __register_event(*call, mod);
- __add_event_to_tracers(*call);
+ if (!__register_event(*call, mod))
+ __add_event_to_tracers(*call);
}
}
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 9a26ac07e324..b6fc33ddb228 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -1027,6 +1027,9 @@ static int regex_match_full(char *str, struct regex *r, int len)
if (!len)
return strcmp(str, r->pattern) == 0;
+ if (len < r->len)
+ return 0;
+
return strncmp(str, r->pattern, len) == 0;
}
diff --git a/kernel/trace/trace_mmiotrace.c b/kernel/trace/trace_mmiotrace.c
index 4d9e5c830dbe..c523ce5aa495 100644
--- a/kernel/trace/trace_mmiotrace.c
+++ b/kernel/trace/trace_mmiotrace.c
@@ -29,6 +29,7 @@ static void mmio_reset_data(struct trace_array *tr)
{
overrun_detected = false;
prev_overruns = 0;
+ atomic_set(&dropped_count, 0);
tracing_reset_online_cpus(&tr->array_buffer);
}
diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
index f72a9926c635..2fa7b596f03e 100644
--- a/kernel/trace/trace_probe.c
+++ b/kernel/trace/trace_probe.c
@@ -1721,7 +1721,11 @@ const char **traceprobe_expand_meta_args(int argc, const char *argv[],
ret = -ENOENT;
goto error;
}
- /* Note: $argN starts from $arg1 */
+ /* Note: $argN starts from $arg1, so $arg0 is invalid. */
+ if (n == 0) {
+ trace_probe_log_err(0, BAD_ARG_NUM);
+ return ERR_PTR(-EINVAL);
+ }
ret = sprint_nth_btf_arg(n - 1, type, buf + used,
bufsize - used, ctx);
if (ret < 0)
diff --git a/kernel/ucount.c b/kernel/ucount.c
index 44ede7a6b805..0ae13e4b6e9f 100644
--- a/kernel/ucount.c
+++ b/kernel/ucount.c
@@ -119,7 +119,7 @@ bool setup_userns_sysctls(struct user_namespace *ns)
void retire_userns_sysctls(struct user_namespace *ns)
{
#ifdef CONFIG_SYSCTL
- struct ctl_table *tbl;
+ const struct ctl_table *tbl;
tbl = ns->sysctls->ctl_table_arg;
unregister_sysctl_table(ns->sysctls);
diff --git a/lib/assoc_array.c b/lib/assoc_array.c
index ca0b4f360c1a..65409f0d2e0e 100644
--- a/lib/assoc_array.c
+++ b/lib/assoc_array.c
@@ -255,7 +255,8 @@ assoc_array_walk(const struct assoc_array *array,
sc_segments = shortcut->index_key[sc_level >> ASSOC_ARRAY_KEY_CHUNK_SHIFT];
dissimilarity = segments ^ sc_segments;
- if (round_up(sc_level, ASSOC_ARRAY_KEY_CHUNK_SIZE) > shortcut->skip_to_level) {
+ if (shortcut->skip_to_level < round_down(sc_level,
+ ASSOC_ARRAY_KEY_CHUNK_SIZE) + ASSOC_ARRAY_KEY_CHUNK_SIZE) {
/* Trim segments that are beyond the shortcut */
int shift = shortcut->skip_to_level & ASSOC_ARRAY_KEY_CHUNK_MASK;
dissimilarity &= ~(ULONG_MAX << shift);
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 6ae2ba8e06a2..4071bf4e81b0 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -734,6 +734,7 @@ int rhashtable_walk_start_check(struct rhashtable_iter *iter)
iter->walker.tbl = rht_dereference_rcu(ht->tbl, ht);
iter->slot = 0;
iter->skip = 0;
+ iter->p = NULL;
return -EAGAIN;
}
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 4443cc44cbf9..ff95a802d158 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -2489,7 +2489,7 @@ static void __split_huge_page_tail(struct folio *folio, int tail,
}
static void __split_huge_page(struct page *page, struct list_head *list,
- pgoff_t end)
+ pgoff_t end, struct address_space *mapping)
{
struct folio *folio = page_folio(page);
struct page *head = &folio->page;
@@ -2564,6 +2564,16 @@ static void __split_huge_page(struct page *page, struct list_head *list,
if (folio_test_swapcache(folio))
split_swap_cluster(folio->swap);
+ /*
+ * Drop the mapping while the head page is still locked and thus pins
+ * the inode. The loop below may free the after-split subpages --
+ * including the head, when @page is a tail beyond EOF that the split
+ * dropped from the page cache -- which could otherwise let the inode,
+ * and @mapping, be freed before this unlock.
+ */
+ if (mapping)
+ i_mmap_unlock_read(mapping);
+
for (i = 0; i < nr; i++) {
struct page *subpage = head + i;
if (subpage == page)
@@ -2745,7 +2755,9 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
}
}
- __split_huge_page(page, list, end);
+ __split_huge_page(page, list, end, mapping);
+ /* __split_huge_page() dropped the i_mmap lock */
+ mapping = NULL;
ret = 0;
} else {
spin_unlock(&ds_queue->split_queue_lock);
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 5da54cef2f72..edae641407b9 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -674,7 +674,7 @@ static int allocate_file_region_entries(struct resv_map *resv,
spin_lock(&resv->lock);
- list_splice(&allocated_regions, &resv->region_cache);
+ list_splice_init(&allocated_regions, &resv->region_cache);
resv->region_cache_count += to_allocate;
}
@@ -5112,8 +5112,12 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
*/
;
} else if (unlikely(is_hugetlb_entry_hwpoisoned(entry))) {
- if (!userfaultfd_wp(dst_vma))
- entry = huge_pte_clear_uffd_wp(entry);
+ /*
+ * A hwpoison entry never carries the uffd-wp bit: it is
+ * installed fresh by make_hwpoison_entry() and
+ * hugetlb_change_protection() leaves it untouched, so
+ * there is nothing to clear for the child.
+ */
set_huge_pte_at(dst, addr, dst_pte, entry, sz);
} else if (unlikely(is_hugetlb_entry_migration(entry))) {
swp_entry_t swp_entry = pte_to_swp_entry(entry);
@@ -5132,7 +5136,7 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
set_huge_pte_at(src, addr, src_pte, entry, sz);
}
if (!userfaultfd_wp(dst_vma))
- entry = huge_pte_clear_uffd_wp(entry);
+ entry = pte_swp_clear_uffd_wp(entry);
set_huge_pte_at(dst, addr, dst_pte, entry, sz);
} else if (unlikely(is_pte_marker(entry))) {
pte_marker marker = copy_pte_marker(
diff --git a/mm/mm_init.c b/mm/mm_init.c
index a71fbb3cec38..1aba3e8737d8 100644
--- a/mm/mm_init.c
+++ b/mm/mm_init.c
@@ -1514,7 +1514,7 @@ void __ref free_area_init_core_hotplug(struct pglist_data *pgdat)
{
int nid = pgdat->node_id;
enum zone_type z;
- int cpu;
+ int cpu, i;
pgdat_init_internals(pgdat);
@@ -1532,10 +1532,17 @@ void __ref free_area_init_core_hotplug(struct pglist_data *pgdat)
pgdat->node_start_pfn = 0;
pgdat->node_present_pages = 0;
- for_each_online_cpu(cpu) {
- struct per_cpu_nodestat *p;
+ /*
+ * Hot-unplug can leave per-cpu vmstat deltas unfolded (folders skip
+ * offline nodes) - reconcile this at online. Foreign access to counters
+ * is safe: the node is not online yet and we hold the hotplug lock.
+ */
+ for_each_possible_cpu(cpu) {
+ struct per_cpu_nodestat *p = per_cpu_ptr(pgdat->per_cpu_nodestats, cpu);
- p = per_cpu_ptr(pgdat->per_cpu_nodestats, cpu);
+ for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++)
+ if (p->vm_node_stat_diff[i])
+ node_page_state_add(p->vm_node_stat_diff[i], pgdat, i);
memset(p, 0, sizeof(*p));
}
diff --git a/mm/page_reporting.c b/mm/page_reporting.c
index 66369cc5279b..d8d735da3475 100644
--- a/mm/page_reporting.c
+++ b/mm/page_reporting.c
@@ -80,7 +80,8 @@ __page_reporting_request(struct page_reporting_dev_info *prdev)
* now we are limiting this to running no more than once every
* couple of seconds.
*/
- schedule_delayed_work(&prdev->work, PAGE_REPORTING_DELAY);
+ queue_delayed_work(system_freezable_wq, &prdev->work,
+ PAGE_REPORTING_DELAY);
}
/* notify prdev of free page reporting request */
@@ -343,7 +344,8 @@ static void page_reporting_process(struct work_struct *work)
*/
state = atomic_cmpxchg(&prdev->state, state, PAGE_REPORTING_IDLE);
if (state == PAGE_REPORTING_REQUESTED)
- schedule_delayed_work(&prdev->work, PAGE_REPORTING_DELAY);
+ queue_delayed_work(system_freezable_wq, &prdev->work,
+ PAGE_REPORTING_DELAY);
}
static DEFINE_MUTEX(page_reporting_mutex);
diff --git a/mm/percpu-km.c b/mm/percpu-km.c
index fe31aa19db81..86d31190524d 100644
--- a/mm/percpu-km.c
+++ b/mm/percpu-km.c
@@ -75,7 +75,7 @@ static struct pcpu_chunk *pcpu_create_chunk(gfp_t gfp)
chunk->base_addr = page_address(pages);
spin_lock_irqsave(&pcpu_lock, flags);
- pcpu_chunk_populated(chunk, 0, nr_pages);
+ pcpu_chunk_populated(chunk, 0, chunk->nr_pages);
spin_unlock_irqrestore(&pcpu_lock, flags);
pcpu_stats_chunk_alloc();
diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c
index db66e11e7fe8..e0128dc9def3 100644
--- a/net/ax25/sysctl_net_ax25.c
+++ b/net/ax25/sysctl_net_ax25.c
@@ -171,7 +171,7 @@ int ax25_register_dev_sysctl(ax25_dev *ax25_dev)
void ax25_unregister_dev_sysctl(ax25_dev *ax25_dev)
{
struct ctl_table_header *header = ax25_dev->sysheader;
- struct ctl_table *table;
+ const struct ctl_table *table;
if (header) {
ax25_dev->sysheader = NULL;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 19ca5016372a..e4364a64ffd5 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -2896,9 +2896,17 @@ static int abort_conn_sync(struct hci_dev *hdev, void *data)
return hci_abort_conn_sync(hdev, conn, conn->abort_reason);
}
+static void abort_conn_destroy(struct hci_dev *hdev, void *data, int err)
+{
+ struct hci_conn *conn = data;
+
+ hci_conn_put(conn);
+}
+
int hci_abort_conn(struct hci_conn *conn, u8 reason)
{
struct hci_dev *hdev = conn->hdev;
+ int err;
/* If abort_reason has already been set it means the connection is
* already being aborted so don't attempt to overwrite it.
@@ -2920,5 +2928,9 @@ int hci_abort_conn(struct hci_conn *conn, u8 reason)
* as a result to MGMT_OP_DISCONNECT/MGMT_OP_UNPAIR which does
* already queue its callback on cmd_sync_work.
*/
- return hci_cmd_sync_run_once(hdev, abort_conn_sync, conn, NULL);
+ err = hci_cmd_sync_run_once(hdev, abort_conn_sync, hci_conn_get(conn),
+ abort_conn_destroy);
+ if (err)
+ hci_conn_put(conn);
+ return (err == -EEXIST) ? 0 : err;
}
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index 4b1fcea37941..6a5ec74eaf25 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -849,7 +849,7 @@ int hci_cmd_sync_run_once(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
void *data, hci_cmd_sync_work_destroy_t destroy)
{
if (hci_cmd_sync_lookup_entry(hdev, func, data, destroy))
- return 0;
+ return -EEXIST;
return hci_cmd_sync_run(hdev, func, data, destroy);
}
@@ -6582,7 +6582,9 @@ static int hci_le_create_conn_sync(struct hci_dev *hdev, void *data)
if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
hdev->le_scan_type == LE_SCAN_ACTIVE &&
!hci_dev_test_flag(hdev, HCI_LE_SIMULTANEOUS_ROLES)) {
- hci_conn_del(conn);
+ conn->state = BT_OPEN;
+ hci_abort_conn_sync(hdev, conn,
+ HCI_ERROR_REJ_LIMITED_RESOURCES);
hci_conn_put(conn);
return -EBUSY;
}
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index c0c4df8cfbc9..84c930e3ac5e 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -546,9 +546,10 @@ static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
}
if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags) &&
- param == session->waiting_report_type) {
+ param == session->waiting_report_type) {
if (session->waiting_report_number < 0 ||
- session->waiting_report_number == skb->data[0]) {
+ (skb->len &&
+ session->waiting_report_number == skb->data[0])) {
/* hidp_get_raw_report() is waiting on this report. */
session->report_return = skb;
done_with_skb = 0;
@@ -563,16 +564,18 @@ static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
static void hidp_recv_ctrl_frame(struct hidp_session *session,
struct sk_buff *skb)
{
- unsigned char hdr, type, param;
+ unsigned char type, param;
+ u8 *hdr;
int free_skb = 1;
BT_DBG("session %p skb %p len %u", session, skb, skb->len);
- hdr = skb->data[0];
- skb_pull(skb, 1);
+ hdr = skb_pull_data(skb, 1);
+ if (!hdr)
+ goto free;
- type = hdr & HIDP_HEADER_TRANS_MASK;
- param = hdr & HIDP_HEADER_PARAM_MASK;
+ type = *hdr & HIDP_HEADER_TRANS_MASK;
+ param = *hdr & HIDP_HEADER_PARAM_MASK;
switch (type) {
case HIDP_TRANS_HANDSHAKE:
@@ -593,6 +596,7 @@ static void hidp_recv_ctrl_frame(struct hidp_session *session,
break;
}
+free:
if (free_skb)
kfree_skb(skb);
}
@@ -600,14 +604,15 @@ static void hidp_recv_ctrl_frame(struct hidp_session *session,
static void hidp_recv_intr_frame(struct hidp_session *session,
struct sk_buff *skb)
{
- unsigned char hdr;
+ u8 *hdr;
BT_DBG("session %p skb %p len %u", session, skb, skb->len);
- hdr = skb->data[0];
- skb_pull(skb, 1);
+ hdr = skb_pull_data(skb, 1);
+ if (!hdr)
+ goto free;
- if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
+ if (*hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
hidp_set_timer(session);
if (session->input)
@@ -619,9 +624,10 @@ static void hidp_recv_intr_frame(struct hidp_session *session,
BT_DBG("report len %d", skb->len);
}
} else {
- BT_DBG("Unsupported protocol header 0x%02x", hdr);
+ BT_DBG("Unsupported protocol header 0x%02x", *hdr);
}
+free:
kfree_skb(skb);
}
diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
index 189b71966992..a67bce151aaf 100644
--- a/net/bluetooth/iso.c
+++ b/net/bluetooth/iso.c
@@ -767,6 +767,7 @@ static void iso_sock_disconn(struct sock *sk)
iso_sock_set_timer(sk, ISO_DISCONN_TIMEOUT);
iso_conn_lock(iso_pi(sk)->conn);
hci_conn_drop(iso_pi(sk)->conn->hcon);
+ iso_pi(sk)->conn->hcon->iso_data = NULL;
iso_pi(sk)->conn->hcon = NULL;
iso_conn_unlock(iso_pi(sk)->conn);
}
@@ -1438,7 +1439,7 @@ static bool check_bcast_qos(struct bt_iso_qos *qos)
return false;
if (!qos->bcast.timeout)
- qos->bcast.sync_timeout = BT_ISO_SYNC_TIMEOUT;
+ qos->bcast.timeout = BT_ISO_SYNC_TIMEOUT;
if (qos->bcast.timeout < 0x000a || qos->bcast.timeout > 0x4000)
return false;
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 792974eef47c..9643a8aacb96 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -4779,6 +4779,10 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
if (!chan)
return -EBADSLT;
+ chan = l2cap_chan_hold_unless_zero(chan);
+ if (!chan)
+ return -EBADSLT;
+
err = 0;
l2cap_chan_lock(chan);
@@ -4824,6 +4828,7 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
}
l2cap_chan_unlock(chan);
+ l2cap_chan_put(chan);
return err;
}
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 979caeb85a42..0422c88ca9ef 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2610,18 +2610,28 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
static bool pending_eir_or_class(struct hci_dev *hdev)
{
struct mgmt_pending_cmd *cmd;
+ bool pending = false;
+
+ mutex_lock(&hdev->mgmt_pending_lock);
list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
switch (cmd->opcode) {
case MGMT_OP_ADD_UUID:
case MGMT_OP_REMOVE_UUID:
case MGMT_OP_SET_DEV_CLASS:
+ case MGMT_OP_SET_LOCAL_NAME:
case MGMT_OP_SET_POWERED:
- return true;
+ pending = true;
+ break;
}
+
+ if (pending)
+ break;
}
- return false;
+ mutex_unlock(&hdev->mgmt_pending_lock);
+
+ return pending;
}
static const u8 bluetooth_base_uuid[] = {
@@ -3427,11 +3437,13 @@ static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
NULL, 0);
}
-static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
+static struct mgmt_pending_cmd *remove_pairing(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
struct mgmt_pending_cmd *cmd;
+ mutex_lock(&hdev->mgmt_pending_lock);
+
list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
continue;
@@ -3439,9 +3451,39 @@ static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
if (cmd->user_data != conn)
continue;
+ list_del(&cmd->list);
+ mutex_unlock(&hdev->mgmt_pending_lock);
return cmd;
}
+ mutex_unlock(&hdev->mgmt_pending_lock);
+
+ return NULL;
+}
+
+static struct mgmt_pending_cmd *remove_pairing_by_addr(struct hci_dev *hdev,
+ bdaddr_t *bdaddr)
+{
+ struct mgmt_pending_cmd *cmd;
+ struct hci_conn *conn;
+
+ mutex_lock(&hdev->mgmt_pending_lock);
+
+ list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
+ if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
+ continue;
+
+ conn = cmd->user_data;
+ if (bacmp(bdaddr, &conn->dst) != 0)
+ continue;
+
+ list_del(&cmd->list);
+ mutex_unlock(&hdev->mgmt_pending_lock);
+ return cmd;
+ }
+
+ mutex_unlock(&hdev->mgmt_pending_lock);
+
return NULL;
}
@@ -3479,10 +3521,10 @@ void mgmt_smp_complete(struct hci_conn *conn, bool complete)
u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
struct mgmt_pending_cmd *cmd;
- cmd = find_pairing(conn);
+ cmd = remove_pairing(conn);
if (cmd) {
cmd->cmd_complete(cmd, status);
- mgmt_pending_remove(cmd);
+ mgmt_pending_free(cmd);
}
}
@@ -3492,14 +3534,14 @@ static void pairing_complete_cb(struct hci_conn *conn, u8 status)
BT_DBG("status %u", status);
- cmd = find_pairing(conn);
+ cmd = remove_pairing(conn);
if (!cmd) {
BT_DBG("Unable to find a pending command");
return;
}
cmd->cmd_complete(cmd, mgmt_status(status));
- mgmt_pending_remove(cmd);
+ mgmt_pending_free(cmd);
}
static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
@@ -3511,14 +3553,14 @@ static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
if (!status)
return;
- cmd = find_pairing(conn);
+ cmd = remove_pairing(conn);
if (!cmd) {
BT_DBG("Unable to find a pending command");
return;
}
cmd->cmd_complete(cmd, mgmt_status(status));
- mgmt_pending_remove(cmd);
+ mgmt_pending_free(cmd);
}
static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
@@ -3674,23 +3716,17 @@ static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
goto unlock;
}
- cmd = pending_find(MGMT_OP_PAIR_DEVICE, hdev);
+ cmd = remove_pairing_by_addr(hdev, &addr->bdaddr);
if (!cmd) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
MGMT_STATUS_INVALID_PARAMS);
goto unlock;
}
- conn = cmd->user_data;
-
- if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
- err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
- MGMT_STATUS_INVALID_PARAMS);
- goto unlock;
- }
+ conn = hci_conn_get(cmd->user_data);
cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
- mgmt_pending_remove(cmd);
+ mgmt_pending_free(cmd);
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
addr, sizeof(*addr));
@@ -3708,6 +3744,8 @@ static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
if (conn->conn_reason == CONN_REASON_PAIR_DEVICE)
hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM);
+ hci_conn_put(conn);
+
unlock:
hci_dev_unlock(hdev);
return err;
@@ -3955,6 +3993,12 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
goto failed;
}
+ if (hdev_is_powered(hdev) && pending_eir_or_class(hdev)) {
+ err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
+ MGMT_STATUS_BUSY);
+ goto failed;
+ }
+
memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
if (!hdev_is_powered(hdev)) {
@@ -10122,14 +10166,14 @@ void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
ev.status = status;
- cmd = find_pairing(conn);
+ cmd = remove_pairing(conn);
mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
cmd ? cmd->sk : NULL);
if (cmd) {
cmd->cmd_complete(cmd, status);
- mgmt_pending_remove(cmd);
+ mgmt_pending_free(cmd);
}
}
diff --git a/net/bridge/br_mrp.c b/net/bridge/br_mrp.c
index fd2de35ffb3c..5fd22bb4f5b6 100644
--- a/net/bridge/br_mrp.c
+++ b/net/bridge/br_mrp.c
@@ -215,7 +215,7 @@ static struct sk_buff *br_mrp_alloc_test_skb(struct br_mrp *mrp,
struct br_mrp_oui_hdr *oui = NULL;
u8 length;
- length = sizeof(*sub_opt) + sizeof(*sub_tlv) + sizeof(oui) +
+ length = sizeof(*sub_opt) + sizeof(*sub_tlv) + sizeof(*oui) +
MRP_OPT_PADDING;
br_mrp_skb_tlv(skb, BR_MRP_TLV_HEADER_OPTION, length);
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 9c91b663bc3b..1625a0776800 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -3684,6 +3684,7 @@ br_multicast_leave_group(struct net_bridge_mcast *brmctx,
p->flags |= MDB_PG_FLAGS_FAST_LEAVE;
br_multicast_del_pg(mp, p, pp);
+ break;
}
goto out;
}
diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
index e6962d693359..64abc62095eb 100644
--- a/net/bridge/br_netfilter_hooks.c
+++ b/net/bridge/br_netfilter_hooks.c
@@ -292,7 +292,11 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_
goto free_skb;
}
- neigh_hh_bridge(&neigh->hh, skb);
+ if (neigh_hh_bridge(&neigh->hh, skb)) {
+ neigh_release(neigh);
+ goto free_skb;
+ }
+
skb->dev = br_indev;
ret = br_handle_frame_finish(net, sk, skb);
@@ -1286,7 +1290,7 @@ static int br_netfilter_sysctl_init_net(struct net *net)
static void br_netfilter_sysctl_exit_net(struct net *net,
struct brnf_net *brnet)
{
- struct ctl_table *table = brnet->ctl_hdr->ctl_table_arg;
+ const struct ctl_table *table = brnet->ctl_hdr->ctl_table_arg;
unregister_net_sysctl_table(brnet->ctl_hdr);
if (!net_eq(net, &init_net))
diff --git a/net/can/af_can.c b/net/can/af_can.c
index e0ad55b9af64..54877f06cd78 100644
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -639,6 +639,16 @@ static int can_rcv_filter(struct can_dev_rcv_lists *dev_rcv_lists, struct sk_buf
return matches;
}
+void can_set_skb_uid(struct sk_buff *skb)
+{
+ /* create non-zero unique skb identifier together with *skb */
+ while (!(skb->hash))
+ skb->hash = atomic_inc_return(&skbcounter);
+
+ skb->sw_hash = 1;
+}
+EXPORT_SYMBOL(can_set_skb_uid);
+
static void can_receive(struct sk_buff *skb, struct net_device *dev)
{
struct can_dev_rcv_lists *dev_rcv_lists;
@@ -650,9 +660,7 @@ static void can_receive(struct sk_buff *skb, struct net_device *dev)
atomic_long_inc(&pkg_stats->rx_frames);
atomic_long_inc(&pkg_stats->rx_frames_delta);
- /* create non-zero unique skb identifier together with *skb */
- while (!(can_skb_prv(skb)->skbcnt))
- can_skb_prv(skb)->skbcnt = atomic_inc_return(&skbcounter);
+ can_set_skb_uid(skb);
rcu_read_lock();
diff --git a/net/can/bcm.c b/net/can/bcm.c
index fcd923c223f4..491495803167 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -338,7 +338,6 @@ static void bcm_can_tx(struct bcm_op *op, struct canfd_frame *cf)
can_skb_reserve(skb);
can_skb_prv(skb)->ifindex = dev->ifindex;
- can_skb_prv(skb)->skbcnt = 0;
skb_put_data(skb, cf, op->cfsiz);
@@ -1582,7 +1581,6 @@ static int bcm_tx_send(struct msghdr *msg, int ifindex, struct sock *sk,
}
can_skb_prv(skb)->ifindex = dev->ifindex;
- can_skb_prv(skb)->skbcnt = 0;
skb->dev = dev;
can_skb_set_owner(skb, sk);
err = can_send(skb, 1); /* send with loopback */
diff --git a/net/can/isotp.c b/net/can/isotp.c
index efc5eeac7c88..fded419bc34f 100644
--- a/net/can/isotp.c
+++ b/net/can/isotp.c
@@ -125,6 +125,15 @@ MODULE_PARM_DESC(max_pdu_size, "maximum isotp pdu size (default "
#define ISOTP_FC_TIMEOUT 1 /* 1 sec */
#define ISOTP_ECHO_TIMEOUT 2 /* 2 secs */
+/* so->tx_result[so->tx_gen % ISOTP_TX_RESULT_SLOTS] holds the packed value
+ * (err << ISOTP_TX_RESULT_GEN_BITS | gen) for each tx generation slot, so it
+ * can be handled with a single READ_ONCE()/WRITE_ONCE() access.
+ */
+#define ISOTP_TX_RESULT_SLOTS 4
+#define ISOTP_TX_RESULT_GEN_BITS 24
+#define ISOTP_TX_RESULT_GEN_MASK ((1U << ISOTP_TX_RESULT_GEN_BITS) - 1)
+#define ISOTP_TX_RESULT_ERR_MASK 0xFF
+
enum {
ISOTP_IDLE = 0,
ISOTP_WAIT_FIRST_FC,
@@ -163,7 +172,8 @@ struct isotp_sock {
u32 force_tx_stmin;
u32 force_rx_stmin;
u32 cfecho; /* consecutive frame echo tag */
- u32 tx_gen; /* generation, bumped per new tx transfer */
+ u32 tx_gen; /* transfer generation, increased per new tx transfer */
+ u32 tx_result[ISOTP_TX_RESULT_SLOTS]; /* per-generation result slots */
struct tpcon rx, tx;
struct list_head notifier;
wait_queue_head_t wait;
@@ -174,6 +184,65 @@ static LIST_HEAD(isotp_notifier_list);
static DEFINE_SPINLOCK(isotp_notifier_lock);
static struct isotp_sock *isotp_busy_notifier;
+/* increase (24 bit) tx generation value */
+static u32 isotp_inc_tx_gen(u32 gen)
+{
+ return (gen + 1) & ISOTP_TX_RESULT_GEN_MASK;
+}
+
+/* store 8 bit error and 24 bit tx generation values in packed u32 element */
+static u32 isotp_pack_tx_result(u32 gen, int err)
+{
+ return gen | ((u32)err << ISOTP_TX_RESULT_GEN_BITS);
+}
+
+/* get the 24 bit tx generation value from the tx result */
+static u32 isotp_get_tx_gen(u32 gen_err)
+{
+ return gen_err & ISOTP_TX_RESULT_GEN_MASK;
+}
+
+/* get the 8 bit error value from the tx result */
+static u32 isotp_get_tx_err(u32 gen_err)
+{
+ return (gen_err >> ISOTP_TX_RESULT_GEN_BITS) & ISOTP_TX_RESULT_ERR_MASK;
+}
+
+/* store transfer result in per-generation%4 so->tx_result[] slot */
+static void isotp_set_tx_result(struct isotp_sock *so, u32 gen, int err)
+{
+ WRITE_ONCE(so->tx_result[gen % ISOTP_TX_RESULT_SLOTS],
+ isotp_pack_tx_result(gen, err));
+}
+
+/* fetch the result recorded for 'gen', as a (negative) errno (0 for success) */
+static int isotp_get_tx_result(struct isotp_sock *so, u32 gen)
+{
+ u32 result = READ_ONCE(so->tx_result[gen % ISOTP_TX_RESULT_SLOTS]);
+
+ if (isotp_get_tx_gen(result) != gen) {
+ pr_notice_once("can-isotp: tx_result[] slot reused before read\n");
+
+ /* report failure rather than risk a false success */
+ return -ECOMM;
+ }
+
+ return -(isotp_get_tx_err(result));
+}
+
+/* true if done, shut down or superseded ('gen' is no longer the active
+ * transfer). Reads tx.state first (acquire) so tx_gen/tx_result reads
+ * below see at least what that state write published (common sequence).
+ */
+static bool isotp_tx_gen_done(struct isotp_sock *so, u32 gen)
+{
+ /* read tx.state first for the common sequence */
+ u32 state = smp_load_acquire(&so->tx.state);
+
+ return state == ISOTP_IDLE || state == ISOTP_SHUTDOWN ||
+ READ_ONCE(so->tx_gen) != gen;
+}
+
static inline struct isotp_sock *isotp_sk(const struct sock *sk)
{
return (struct isotp_sock *)sk;
@@ -196,7 +265,7 @@ static enum hrtimer_restart isotp_rx_timer_handler(struct hrtimer *hrtimer)
rxtimer);
struct sock *sk = &so->sk;
- if (so->rx.state == ISOTP_WAIT_DATA) {
+ if (READ_ONCE(so->rx.state) == ISOTP_WAIT_DATA) {
/* we did not get new data frames in time */
/* report 'connection timed out' */
@@ -205,7 +274,7 @@ static enum hrtimer_restart isotp_rx_timer_handler(struct hrtimer *hrtimer)
sk_error_report(sk);
/* reset rx state */
- so->rx.state = ISOTP_IDLE;
+ WRITE_ONCE(so->rx.state, ISOTP_IDLE);
}
return HRTIMER_NORESTART;
@@ -231,7 +300,6 @@ static int isotp_send_fc(struct sock *sk, int ae, u8 flowstatus)
can_skb_reserve(nskb);
can_skb_prv(nskb)->ifindex = dev->ifindex;
- can_skb_prv(nskb)->skbcnt = 0;
nskb->dev = dev;
can_skb_set_owner(nskb, sk);
@@ -363,20 +431,19 @@ static void isotp_send_cframe(struct isotp_sock *so);
static int isotp_rcv_fc(struct isotp_sock *so, struct canfd_frame *cf, int ae)
{
struct sock *sk = &so->sk;
+ int tx_err = EBADMSG; /* default for unknown FC status */
- if (so->tx.state != ISOTP_WAIT_FC &&
- so->tx.state != ISOTP_WAIT_FIRST_FC)
+ if (READ_ONCE(so->tx.state) != ISOTP_WAIT_FC &&
+ READ_ONCE(so->tx.state) != ISOTP_WAIT_FIRST_FC)
return 0;
hrtimer_cancel(&so->txtimer);
/* isotp_tx_timeout() may have given up on this job while
- * hrtimer_cancel() above waited for it to finish; so->rx_lock
- * (held by our caller isotp_rcv()) rules out a concurrent claim,
- * so a plain recheck is enough here.
+ * hrtimer_cancel() above waited for it to finish => recheck
*/
- if (so->tx.state != ISOTP_WAIT_FC &&
- so->tx.state != ISOTP_WAIT_FIRST_FC)
+ if (READ_ONCE(so->tx.state) != ISOTP_WAIT_FC &&
+ READ_ONCE(so->tx.state) != ISOTP_WAIT_FIRST_FC)
return 1;
if ((cf->len < ae + FC_CONTENT_SZ) ||
@@ -387,13 +454,15 @@ static int isotp_rcv_fc(struct isotp_sock *so, struct canfd_frame *cf, int ae)
if (!sock_flag(sk, SOCK_DEAD))
sk_error_report(sk);
- so->tx.state = ISOTP_IDLE;
+ isotp_set_tx_result(so, so->tx_gen, EBADMSG);
+ /* set to IDLE after publishing tx_result */
+ smp_store_release(&so->tx.state, ISOTP_IDLE);
wake_up_interruptible(&so->wait);
return 1;
}
/* get communication parameters only from the first FC frame */
- if (so->tx.state == ISOTP_WAIT_FIRST_FC) {
+ if (READ_ONCE(so->tx.state) == ISOTP_WAIT_FIRST_FC) {
so->txfc.bs = cf->data[ae + 1];
so->txfc.stmin = cf->data[ae + 2];
@@ -416,13 +485,13 @@ static int isotp_rcv_fc(struct isotp_sock *so, struct canfd_frame *cf, int ae)
so->tx_gap = ktime_add_ns(so->tx_gap,
(so->txfc.stmin - 0xF0)
* 100000);
- so->tx.state = ISOTP_WAIT_FC;
+ WRITE_ONCE(so->tx.state, ISOTP_WAIT_FC);
}
switch (cf->data[ae] & 0x0F) {
case ISOTP_FC_CTS:
so->tx.bs = 0;
- so->tx.state = ISOTP_SENDING;
+ WRITE_ONCE(so->tx.state, ISOTP_SENDING);
/* send CF frame and enable echo timeout handling */
hrtimer_start(&so->echotimer, ktime_set(ISOTP_ECHO_TIMEOUT, 0),
HRTIMER_MODE_REL_SOFT);
@@ -437,14 +506,19 @@ static int isotp_rcv_fc(struct isotp_sock *so, struct canfd_frame *cf, int ae)
case ISOTP_FC_OVFLW:
/* overflow on receiver side - report 'message too long' */
- sk->sk_err = EMSGSIZE;
- if (!sock_flag(sk, SOCK_DEAD))
- sk_error_report(sk);
+ tx_err = EMSGSIZE;
fallthrough;
default:
- /* stop this tx job */
- so->tx.state = ISOTP_IDLE;
+ /* reserved/unknown flow status (tx_err defaults to EBADMSG) */
+
+ sk->sk_err = tx_err;
+ if (!sock_flag(sk, SOCK_DEAD))
+ sk_error_report(sk);
+
+ isotp_set_tx_result(so, so->tx_gen, tx_err);
+ /* set to IDLE after publishing tx_result */
+ smp_store_release(&so->tx.state, ISOTP_IDLE);
wake_up_interruptible(&so->wait);
}
return 0;
@@ -457,7 +531,7 @@ static int isotp_rcv_sf(struct sock *sk, struct canfd_frame *cf, int pcilen,
struct sk_buff *nskb;
hrtimer_cancel(&so->rxtimer);
- so->rx.state = ISOTP_IDLE;
+ WRITE_ONCE(so->rx.state, ISOTP_IDLE);
if (!len || len > cf->len - pcilen)
return 1;
@@ -491,7 +565,7 @@ static int isotp_rcv_ff(struct sock *sk, struct canfd_frame *cf, int ae)
int ff_pci_sz;
hrtimer_cancel(&so->rxtimer);
- so->rx.state = ISOTP_IDLE;
+ WRITE_ONCE(so->rx.state, ISOTP_IDLE);
/* get the used sender LL_DL from the (first) CAN frame data length */
so->rx.ll_dl = padlen(cf->len);
@@ -545,7 +619,7 @@ static int isotp_rcv_ff(struct sock *sk, struct canfd_frame *cf, int ae)
/* initial setup for this pdu reception */
so->rx.sn = 1;
- so->rx.state = ISOTP_WAIT_DATA;
+ WRITE_ONCE(so->rx.state, ISOTP_WAIT_DATA);
/* no creation of flow control frames */
if (so->opt.flags & CAN_ISOTP_LISTEN_MODE)
@@ -563,7 +637,7 @@ static int isotp_rcv_cf(struct sock *sk, struct canfd_frame *cf, int ae,
struct sk_buff *nskb;
int i;
- if (so->rx.state != ISOTP_WAIT_DATA)
+ if (READ_ONCE(so->rx.state) != ISOTP_WAIT_DATA)
return 0;
/* drop if timestamp gap is less than force_rx_stmin nano secs */
@@ -578,11 +652,9 @@ static int isotp_rcv_cf(struct sock *sk, struct canfd_frame *cf, int ae,
hrtimer_cancel(&so->rxtimer);
/* isotp_rx_timer_handler() may have raced us for so->rx.state
- * while hrtimer_cancel() above waited for it to finish, already
- * reporting ETIMEDOUT and resetting the reception; don't process
- * this CF into a reassembly that has already been given up on.
+ * while hrtimer_cancel() above waited for it to finish => recheck
*/
- if (so->rx.state != ISOTP_WAIT_DATA)
+ if (READ_ONCE(so->rx.state) != ISOTP_WAIT_DATA)
return 1;
/* CFs are never longer than the FF */
@@ -603,7 +675,7 @@ static int isotp_rcv_cf(struct sock *sk, struct canfd_frame *cf, int ae,
sk_error_report(sk);
/* reset rx state */
- so->rx.state = ISOTP_IDLE;
+ WRITE_ONCE(so->rx.state, ISOTP_IDLE);
return 1;
}
so->rx.sn++;
@@ -617,7 +689,7 @@ static int isotp_rcv_cf(struct sock *sk, struct canfd_frame *cf, int ae,
if (so->rx.idx >= so->rx.len) {
/* we are done */
- so->rx.state = ISOTP_IDLE;
+ WRITE_ONCE(so->rx.state, ISOTP_IDLE);
if ((so->opt.flags & ISOTP_CHECK_PADDING) &&
check_pad(so, cf, i + 1, so->opt.rxpad_content)) {
@@ -688,8 +760,10 @@ static void isotp_rcv(struct sk_buff *skb, void *data)
if (so->opt.flags & CAN_ISOTP_HALF_DUPLEX) {
/* check rx/tx path half duplex expectations */
- if ((so->tx.state != ISOTP_IDLE && n_pci_type != N_PCI_FC) ||
- (so->rx.state != ISOTP_IDLE && n_pci_type == N_PCI_FC))
+ if ((READ_ONCE(so->tx.state) != ISOTP_IDLE &&
+ n_pci_type != N_PCI_FC) ||
+ (READ_ONCE(so->rx.state) != ISOTP_IDLE &&
+ n_pci_type == N_PCI_FC))
goto out_unlock;
}
@@ -783,6 +857,7 @@ static void isotp_send_cframe(struct isotp_sock *so)
struct canfd_frame *cf;
int can_send_ret;
int ae = (so->opt.flags & CAN_ISOTP_EXTEND_ADDR) ? 1 : 0;
+ u32 old_cfecho;
dev = dev_get_by_index(sock_net(sk), so->ifindex);
if (!dev)
@@ -796,7 +871,9 @@ static void isotp_send_cframe(struct isotp_sock *so)
can_skb_reserve(skb);
can_skb_prv(skb)->ifindex = dev->ifindex;
- can_skb_prv(skb)->skbcnt = 0;
+
+ /* set uid in tx skb to identify CF echo frames */
+ can_set_skb_uid(skb);
cf = (struct canfd_frame *)skb->data;
skb_put_zero(skb, so->ll.mtu);
@@ -814,12 +891,15 @@ static void isotp_send_cframe(struct isotp_sock *so)
skb->dev = dev;
can_skb_set_owner(skb, sk);
- /* cfecho should have been zero'ed by init/isotp_rcv_echo() */
- if (so->cfecho)
- pr_notice_once("can-isotp: cfecho is %08X != 0\n", so->cfecho);
+ /* zero'ed by init/isotp_rcv_echo(); reached lock-free via
+ * isotp_txfr_timer_handler() too, so use READ_ONCE()/WRITE_ONCE()
+ */
+ old_cfecho = READ_ONCE(so->cfecho);
+ if (old_cfecho)
+ pr_notice_once("can-isotp: cfecho is %08X != 0\n", old_cfecho);
/* set consecutive frame echo tag */
- so->cfecho = *(u32 *)cf->data;
+ WRITE_ONCE(so->cfecho, skb->hash);
/* send frame with local echo enabled */
can_send_ret = can_send(skb, 1);
@@ -871,7 +951,6 @@ static void isotp_rcv_echo(struct sk_buff *skb, void *data)
{
struct sock *sk = (struct sock *)data;
struct isotp_sock *so = isotp_sk(sk);
- struct canfd_frame *cf = (struct canfd_frame *)skb->data;
/* only handle my own local echo CF/SF skb's (no FF!) */
if (skb->sk != sk)
@@ -883,32 +962,35 @@ static void isotp_rcv_echo(struct sk_buff *skb, void *data)
spin_lock(&so->rx_lock);
/* so->cfecho may since belong to a new transfer; recheck under lock */
- if (so->cfecho != *(u32 *)cf->data)
+ if (READ_ONCE(so->cfecho) != skb->hash)
goto out_unlock;
/* cancel local echo timeout */
hrtimer_cancel(&so->echotimer);
/* local echo skb with consecutive frame has been consumed */
- so->cfecho = 0;
+ WRITE_ONCE(so->cfecho, 0);
/* claiming a transfer also takes so->rx_lock, so a plain recheck
* is enough: so->tx.state can't have flipped to ISOTP_SENDING for
* a new claim while we're still in here
*/
- if (so->tx.state != ISOTP_SENDING)
+ if (READ_ONCE(so->tx.state) != ISOTP_SENDING)
goto out_unlock;
if (so->tx.idx >= so->tx.len) {
/* we are done */
- so->tx.state = ISOTP_IDLE;
+
+ isotp_set_tx_result(so, so->tx_gen, 0);
+ /* set to IDLE after publishing tx_result */
+ smp_store_release(&so->tx.state, ISOTP_IDLE);
wake_up_interruptible(&so->wait);
goto out_unlock;
}
if (so->txfc.bs && so->tx.bs >= so->txfc.bs) {
/* stop and wait for FC with timeout */
- so->tx.state = ISOTP_WAIT_FC;
+ WRITE_ONCE(so->tx.state, ISOTP_WAIT_FC);
hrtimer_start(&so->txtimer, ktime_set(ISOTP_FC_TIMEOUT, 0),
HRTIMER_MODE_REL_SOFT);
goto out_unlock;
@@ -930,16 +1012,20 @@ static void isotp_rcv_echo(struct sk_buff *skb, void *data)
spin_unlock(&so->rx_lock);
}
-/* shared by so->txtimer's and so->echotimer's callbacks. Both timers get
- * cancelled under so->rx_lock elsewhere, so this must stay lock-free to
- * avoid deadlocking with that; uses so->tx_gen instead to avoid tainting
- * a new transfer with an error from the one that just timed out.
+/* isotp_tx_timeout: we did not get any flow control or echo frame in time
+ *
+ * Shared by so->txtimer's and so->echotimer's callbacks. Both timers get
+ * cancelled under so->rx_lock elsewhere, so this must stay lock-free.
+ *
+ * tx.state is acquired before tx_gen. Common sequence in isotp_tx_gen_done().
+ * cmpxchg() only orders itself, not the two preceding loads.
*/
static enum hrtimer_restart isotp_tx_timeout(struct isotp_sock *so)
{
struct sock *sk = &so->sk;
+ /* read tx.state first for the common sequence */
+ u32 old_state = smp_load_acquire(&so->tx.state);
u32 gen = READ_ONCE(so->tx_gen);
- u32 old_state = READ_ONCE(so->tx.state);
/* don't handle timeouts in IDLE or SHUTDOWN state */
if (old_state == ISOTP_IDLE || old_state == ISOTP_SHUTDOWN)
@@ -949,14 +1035,14 @@ static enum hrtimer_restart isotp_tx_timeout(struct isotp_sock *so)
if (cmpxchg(&so->tx.state, old_state, ISOTP_IDLE) != old_state)
return HRTIMER_NORESTART;
- /* we did not get any flow control or echo frame in time */
+ /* detected timeout: report 'communication error on send' */
- if (READ_ONCE(so->tx_gen) == gen) {
- /* report 'communication error on send' */
- sk->sk_err = ECOMM;
- if (!sock_flag(sk, SOCK_DEAD))
- sk_error_report(sk);
- }
+ /* a stale read of this slot by a waiter still falls back to ECOMM */
+ isotp_set_tx_result(so, gen, ECOMM);
+
+ sk->sk_err = ECOMM;
+ if (!sock_flag(sk, SOCK_DEAD))
+ sk_error_report(sk);
wake_up_interruptible(&so->wait);
@@ -991,7 +1077,7 @@ static enum hrtimer_restart isotp_txfr_timer_handler(struct hrtimer *hrtimer)
HRTIMER_MODE_REL_SOFT);
/* cfecho should be consumed by isotp_rcv_echo() here */
- if (so->tx.state == ISOTP_SENDING && !so->cfecho)
+ if (READ_ONCE(so->tx.state) == ISOTP_SENDING && !READ_ONCE(so->cfecho))
isotp_send_cframe(so);
return HRTIMER_NORESTART;
@@ -1009,10 +1095,12 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
s64 hrtimer_sec = ISOTP_ECHO_TIMEOUT;
struct hrtimer *tx_hrt = &so->echotimer;
u32 new_state = ISOTP_SENDING;
+ u32 my_gen;
+ u32 old_cfecho;
int off;
int err;
- if (!so->bound || so->tx.state == ISOTP_SHUTDOWN)
+ if (!so->bound || READ_ONCE(so->tx.state) == ISOTP_SHUTDOWN)
return -EADDRNOTAVAIL;
/* claim the socket under so->rx_lock: this serializes the claim
@@ -1029,29 +1117,33 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
if (msg->msg_flags & MSG_DONTWAIT)
return -EAGAIN;
- if (so->tx.state == ISOTP_SHUTDOWN)
+ if (READ_ONCE(so->tx.state) == ISOTP_SHUTDOWN)
return -EADDRNOTAVAIL;
/* wait for complete transmission of current pdu */
err = wait_event_interruptible(so->wait,
- so->tx.state == ISOTP_IDLE);
+ READ_ONCE(so->tx.state) == ISOTP_IDLE ||
+ READ_ONCE(so->tx.state) == ISOTP_SHUTDOWN);
if (err)
return err;
}
- /* new transfer: bump so->tx_gen and drain the old one's timers,
- * still under the so->rx_lock we just claimed the socket with
- */
- WRITE_ONCE(so->tx.state, ISOTP_SENDING);
- WRITE_ONCE(so->tx_gen, READ_ONCE(so->tx_gen) + 1);
+ /* txfrtimer's callback re-arms echotimer lock-free: drain it first */
+ hrtimer_cancel(&so->txfrtimer);
hrtimer_cancel(&so->txtimer);
hrtimer_cancel(&so->echotimer);
- hrtimer_cancel(&so->txfrtimer);
- so->cfecho = 0;
+
+ /* new transfer: increment so->tx_gen and set tx.state after barrier */
+ my_gen = isotp_inc_tx_gen(READ_ONCE(so->tx_gen));
+ isotp_set_tx_result(so, my_gen, ECOMM); /* prevent stale slot matching */
+ WRITE_ONCE(so->tx_gen, my_gen);
+ smp_wmb(); /* see smp_load_acquire() in isotp_tx_[timeout|gen_done] */
+ WRITE_ONCE(so->tx.state, ISOTP_SENDING);
+ WRITE_ONCE(so->cfecho, 0);
spin_unlock_bh(&so->rx_lock);
/* so->bound is only checked once above - a wakeup may have
- * unbound/rebound the socket meanwhile, so re-validate it
+ * unbound/rebound the socket meanwhile => recheck
*/
if (!so->bound) {
err = -EADDRNOTAVAIL;
@@ -1102,7 +1194,9 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
can_skb_reserve(skb);
can_skb_prv(skb)->ifindex = dev->ifindex;
- can_skb_prv(skb)->skbcnt = 0;
+
+ /* set uid in tx skb to identify CF echo frames */
+ can_set_skb_uid(skb);
so->tx.len = size;
so->tx.idx = 0;
@@ -1111,8 +1205,9 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
skb_put_zero(skb, so->ll.mtu);
/* cfecho should have been zero'ed by init / former isotp_rcv_echo() */
- if (so->cfecho)
- pr_notice_once("can-isotp: uninit cfecho %08X\n", so->cfecho);
+ old_cfecho = READ_ONCE(so->cfecho);
+ if (old_cfecho)
+ pr_notice_once("can-isotp: uninit cfecho %08X\n", old_cfecho);
/* check for single frame transmission depending on TX_DL */
if (size <= so->tx.ll_dl - SF_PCI_SZ4 - ae - off) {
@@ -1140,7 +1235,7 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
cf->data[ae] |= size;
/* set CF echo tag for isotp_rcv_echo() (SF-mode) */
- so->cfecho = *(u32 *)cf->data;
+ WRITE_ONCE(so->cfecho, skb->hash);
} else {
/* send first frame */
@@ -1157,7 +1252,7 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
so->txfc.bs = 0;
/* set CF echo tag for isotp_rcv_echo() (CF-mode) */
- so->cfecho = *(u32 *)cf->data;
+ WRITE_ONCE(so->cfecho, skb->hash);
} else {
/* standard flow control check */
new_state = ISOTP_WAIT_FIRST_FC;
@@ -1167,12 +1262,12 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
tx_hrt = &so->txtimer;
/* no CF echo tag for isotp_rcv_echo() (FF-mode) */
- so->cfecho = 0;
+ WRITE_ONCE(so->cfecho, 0);
}
}
spin_lock_bh(&so->rx_lock);
- if (so->tx.state == ISOTP_SHUTDOWN) {
+ if (READ_ONCE(so->tx.state) == ISOTP_SHUTDOWN) {
/* isotp_release() has since taken over and already drained
* our timers - don't send into a socket that's going away
*/
@@ -1183,7 +1278,7 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
return -EADDRNOTAVAIL;
}
/* WAIT_FIRST_FC for standard FF, else stays ISOTP_SENDING */
- so->tx.state = new_state;
+ WRITE_ONCE(so->tx.state, new_state);
hrtimer_start(tx_hrt, ktime_set(hrtimer_sec, 0),
HRTIMER_MODE_REL_SOFT);
spin_unlock_bh(&so->rx_lock);
@@ -1200,20 +1295,49 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
__func__, ERR_PTR(err));
spin_lock_bh(&so->rx_lock);
+
+ /* new transfer already claimed by a concurrent completion,
+ * timeout or sendmsg() while we were stuck in can_send()?
+ */
+ if (READ_ONCE(so->tx_gen) != my_gen) {
+ /* don't touch timers and state of the new transfer */
+ spin_unlock_bh(&so->rx_lock);
+ return err;
+ }
+
/* no transmission -> no timeout monitoring */
hrtimer_cancel(tx_hrt);
goto err_out_drop_locked;
}
if (wait_tx_done) {
- /* wait for complete transmission of current pdu */
- err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
+ /* wake up for:
+ * - concurrent sendmsg() claiming a new transfer
+ * - complete transmission of current PDU
+ * - shutdown state change in isotp_release()
+ * isotp_tx_gen_done() uses common tx.state/tx_gen read sequence
+ */
+ err = wait_event_interruptible(so->wait,
+ isotp_tx_gen_done(so, my_gen));
if (err)
goto err_event_drop;
- err = sock_error(sk);
- if (err)
- return err;
+ /* still our claim, but isotp_release() force-shut it down */
+ if (smp_load_acquire(&so->tx.state) == ISOTP_SHUTDOWN &&
+ READ_ONCE(so->tx_gen) == my_gen) {
+ err = -EADDRNOTAVAIL;
+ goto err_event_drop;
+ }
+
+ /* own completion, or tx_gen moved on - either way this is
+ * what isotp_get_tx_result() recorded for my_gen
+ */
+ err = isotp_get_tx_result(so, my_gen);
+
+ /* drain to avoid stale error for a later poll()/SO_ERROR */
+ sock_error(sk);
+
+ return err ? err : size;
}
return size;
@@ -1223,15 +1347,26 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
spin_lock_bh(&so->rx_lock);
goto err_out_drop_locked;
err_event_drop:
- /* interrupted waiting on our own transfer - drain its timers */
+ /* interrupted or shut down while waiting on our own transfer */
spin_lock_bh(&so->rx_lock);
+
+ /* new transfer already started by concurrent sendmsg()? */
+ if (READ_ONCE(so->tx_gen) != my_gen) {
+ /* don't touch timers and states of the new transfer */
+ spin_unlock_bh(&so->rx_lock);
+ return err;
+ }
+
hrtimer_cancel(&so->txfrtimer);
hrtimer_cancel(&so->txtimer);
hrtimer_cancel(&so->echotimer);
err_out_drop_locked:
/* release the claim; so->rx_lock still held from above */
- so->cfecho = 0;
- so->tx.state = ISOTP_IDLE;
+ WRITE_ONCE(so->cfecho, 0);
+
+ /* only claim to IDLE if isotp_release() has not taken over */
+ if (READ_ONCE(so->tx.state) != ISOTP_SHUTDOWN)
+ WRITE_ONCE(so->tx.state, ISOTP_IDLE);
spin_unlock_bh(&so->rx_lock);
wake_up_interruptible(&so->wait);
@@ -1297,8 +1432,9 @@ static int isotp_release(struct socket *sock)
/* best-effort: wait for a running pdu to finish, but don't block on
* it forever - give up after the first signal
*/
- while (so->tx.state != ISOTP_IDLE &&
- wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE) == 0)
+ while (READ_ONCE(so->tx.state) != ISOTP_IDLE &&
+ wait_event_interruptible(so->wait,
+ READ_ONCE(so->tx.state) == ISOTP_IDLE) == 0)
;
/* claim the socket under so->rx_lock like sendmsg() does, so its
@@ -1306,9 +1442,12 @@ static int isotp_release(struct socket *sock)
* unconditionally, even when a signal cut the wait above short
*/
spin_lock_bh(&so->rx_lock);
- so->tx.state = ISOTP_SHUTDOWN;
+ WRITE_ONCE(so->tx.state, ISOTP_SHUTDOWN);
spin_unlock_bh(&so->rx_lock);
- so->rx.state = ISOTP_IDLE;
+ WRITE_ONCE(so->rx.state, ISOTP_IDLE);
+
+ /* forced SHUTDOWN may have skipped IDLE (gave up on a signal) */
+ wake_up_interruptible(&so->wait);
spin_lock(&isotp_notifier_lock);
while (isotp_busy_notifier == so) {
@@ -1423,7 +1562,8 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
* with so->bound in the same lock_sock() section above, so there is
* no window in which a concurrent isotp_notify() could be missed.
*/
- if (so->tx.state != ISOTP_IDLE || so->rx.state != ISOTP_IDLE) {
+ if (READ_ONCE(so->tx.state) != ISOTP_IDLE ||
+ READ_ONCE(so->rx.state) != ISOTP_IDLE) {
err = -EAGAIN;
goto out;
}
@@ -1457,7 +1597,7 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
isotp_rcv, sk, "isotp", sk);
/* no consecutive frame echo skb in flight */
- so->cfecho = 0;
+ WRITE_ONCE(so->cfecho, 0);
/* register for echo skb's */
can_rx_register(net, dev, tx_id, SINGLE_MASK(tx_id),
@@ -1823,7 +1963,7 @@ static __poll_t isotp_poll(struct file *file, struct socket *sock, poll_table *w
poll_wait(file, &so->wait, wait);
/* Check for false positives due to TX state */
- if ((mask & EPOLLWRNORM) && (so->tx.state != ISOTP_IDLE))
+ if ((mask & EPOLLWRNORM) && (READ_ONCE(so->tx.state) != ISOTP_IDLE))
mask &= ~(EPOLLOUT | EPOLLWRNORM);
return mask;
@@ -1883,13 +2023,18 @@ static __init int isotp_module_init(void)
pr_info("can: isotp protocol (max_pdu_size %d)\n", max_pdu_size);
+ err = register_netdevice_notifier(&canisotp_notifier);
+ if (err)
+ return err;
+
err = can_proto_register(&isotp_can_proto);
- if (err < 0)
+ if (err < 0) {
pr_err("can: registration of isotp protocol failed %pe\n", ERR_PTR(err));
- else
- register_netdevice_notifier(&canisotp_notifier);
+ unregister_netdevice_notifier(&canisotp_notifier);
+ return err;
+ }
- return err;
+ return 0;
}
static __exit void isotp_module_exit(void)
diff --git a/net/can/j1939/bus.c b/net/can/j1939/bus.c
index e0b966c2517c..aabe4fa91543 100644
--- a/net/can/j1939/bus.c
+++ b/net/can/j1939/bus.c
@@ -20,6 +20,7 @@ static void __j1939_ecu_release(struct kref *kref)
struct j1939_priv *priv = ecu->priv;
list_del(&ecu->list);
+ netdev_put(priv->ndev, &ecu->priv_dev_tracker);
kfree(ecu);
j1939_priv_put(priv);
}
@@ -155,6 +156,7 @@ struct j1939_ecu *j1939_ecu_create_locked(struct j1939_priv *priv, name_t name)
if (!ecu)
return ERR_PTR(-ENOMEM);
kref_init(&ecu->kref);
+ netdev_hold(priv->ndev, &ecu->priv_dev_tracker, gfp_any());
ecu->addr = J1939_IDLE_ADDR;
ecu->name = name;
diff --git a/net/can/j1939/j1939-priv.h b/net/can/j1939/j1939-priv.h
index 31a93cae5111..1d3d5d0551e0 100644
--- a/net/can/j1939/j1939-priv.h
+++ b/net/can/j1939/j1939-priv.h
@@ -38,6 +38,7 @@ struct j1939_ecu {
struct hrtimer ac_timer;
struct kref kref;
struct j1939_priv *priv;
+ netdevice_tracker priv_dev_tracker;
/* count users, to help transport protocol decide for interaction */
int nusers;
@@ -60,6 +61,7 @@ struct j1939_priv {
rwlock_t lock;
struct net_device *ndev;
+ netdevice_tracker dev_tracker;
/* list of 256 ecu ptrs, that cache the claimed addresses.
* also protected by the above lock
@@ -229,6 +231,7 @@ enum j1939_session_state {
struct j1939_session {
struct j1939_priv *priv;
+ netdevice_tracker priv_dev_tracker;
struct list_head active_session_list_entry;
struct list_head sk_session_queue_entry;
struct kref kref;
diff --git a/net/can/j1939/main.c b/net/can/j1939/main.c
index 7e8a20f2fc42..b45f834ff2cf 100644
--- a/net/can/j1939/main.c
+++ b/net/can/j1939/main.c
@@ -137,7 +137,7 @@ static struct j1939_priv *j1939_priv_create(struct net_device *ndev)
priv->ndev = ndev;
kref_init(&priv->kref);
kref_init(&priv->rx_kref);
- dev_hold(ndev);
+ netdev_hold(ndev, &priv->dev_tracker, GFP_KERNEL);
netdev_dbg(priv->ndev, "%s : 0x%p\n", __func__, priv);
@@ -163,7 +163,7 @@ static void __j1939_priv_release(struct kref *kref)
WARN_ON_ONCE(!list_empty(&priv->ecus));
WARN_ON_ONCE(!list_empty(&priv->j1939_socks));
- dev_put(ndev);
+ netdev_put(ndev, &priv->dev_tracker);
kfree(priv);
}
@@ -281,7 +281,7 @@ struct j1939_priv *j1939_netdev_start(struct net_device *ndev)
*/
kref_get(&priv_new->rx_kref);
mutex_unlock(&j1939_netdev_lock);
- dev_put(ndev);
+ netdev_put(ndev, &priv->dev_tracker);
kfree(priv);
return priv_new;
}
@@ -298,7 +298,7 @@ struct j1939_priv *j1939_netdev_start(struct net_device *ndev)
j1939_priv_set(ndev, NULL);
mutex_unlock(&j1939_netdev_lock);
- dev_put(ndev);
+ netdev_put(ndev, &priv->dev_tracker);
kfree(priv);
return ERR_PTR(ret);
diff --git a/net/can/j1939/socket.c b/net/can/j1939/socket.c
index 7bf4d4fb9673..4a76f7434e1e 100644
--- a/net/can/j1939/socket.c
+++ b/net/can/j1939/socket.c
@@ -889,7 +889,6 @@ static struct sk_buff *j1939_sk_alloc_skb(struct net_device *ndev,
can_skb_reserve(skb);
can_skb_prv(skb)->ifindex = ndev->ifindex;
- can_skb_prv(skb)->skbcnt = 0;
skb_reserve(skb, offsetof(struct can_frame, data));
ret = memcpy_from_msg(skb_put(skb, size), msg, size);
diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c
index d8dada03b3cd..a262a58588c2 100644
--- a/net/can/j1939/transport.c
+++ b/net/can/j1939/transport.c
@@ -282,6 +282,7 @@ static void j1939_session_destroy(struct j1939_session *session)
kfree_skb(skb);
}
__j1939_session_drop(session);
+ netdev_put(session->priv->ndev, &session->priv_dev_tracker);
j1939_priv_put(session->priv);
kfree(session);
}
@@ -612,7 +613,6 @@ sk_buff *j1939_tp_tx_dat_new(struct j1939_priv *priv,
skb->dev = priv->ndev;
can_skb_reserve(skb);
can_skb_prv(skb)->ifindex = priv->ndev->ifindex;
- can_skb_prv(skb)->skbcnt = 0;
/* reserve CAN header */
skb_reserve(skb, offsetof(struct can_frame, data));
@@ -1510,6 +1510,7 @@ static struct j1939_session *j1939_session_new(struct j1939_priv *priv,
INIT_LIST_HEAD(&session->active_session_list_entry);
INIT_LIST_HEAD(&session->sk_session_queue_entry);
kref_init(&session->kref);
+ netdev_hold(priv->ndev, &session->priv_dev_tracker, gfp_any());
j1939_priv_get(priv);
session->priv = priv;
@@ -1551,7 +1552,6 @@ j1939_session *j1939_session_fresh_new(struct j1939_priv *priv,
skb->dev = priv->ndev;
can_skb_reserve(skb);
can_skb_prv(skb)->ifindex = priv->ndev->ifindex;
- can_skb_prv(skb)->skbcnt = 0;
skcb = j1939_skb_to_cb(skb);
memcpy(skcb, rel_skcb, sizeof(*skcb));
@@ -1562,7 +1562,7 @@ j1939_session *j1939_session_fresh_new(struct j1939_priv *priv,
}
/* alloc data area */
- skb_put(skb, size);
+ skb_put_zero(skb, size);
/* skb is recounted in j1939_session_new() */
return session;
}
diff --git a/net/can/raw.c b/net/can/raw.c
index 939d11bd4562..ad4b16476743 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -75,8 +75,8 @@ MODULE_ALIAS("can-proto-1");
*/
struct uniqframe {
- int skbcnt;
const struct sk_buff *skb;
+ u32 hash;
unsigned int join_rx_count;
};
@@ -140,7 +140,7 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
/* eliminate multiple filter matches for the same skb */
if (this_cpu_ptr(ro->uniq)->skb == oskb &&
- this_cpu_ptr(ro->uniq)->skbcnt == can_skb_prv(oskb)->skbcnt) {
+ this_cpu_ptr(ro->uniq)->hash == oskb->hash) {
if (!ro->join_filters)
return;
@@ -150,7 +150,7 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
return;
} else {
this_cpu_ptr(ro->uniq)->skb = oskb;
- this_cpu_ptr(ro->uniq)->skbcnt = can_skb_prv(oskb)->skbcnt;
+ this_cpu_ptr(ro->uniq)->hash = oskb->hash;
this_cpu_ptr(ro->uniq)->join_rx_count = 1;
/* drop first frame to check all enabled filters? */
if (ro->join_filters && ro->count > 1)
@@ -871,7 +871,6 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
can_skb_reserve(skb);
can_skb_prv(skb)->ifindex = dev->ifindex;
- can_skb_prv(skb)->skbcnt = 0;
/* fill the skb before testing for valid CAN frames */
err = memcpy_from_msg(skb_put(skb, size), msg, size);
diff --git a/net/core/lwt_bpf.c b/net/core/lwt_bpf.c
index efbd9eecb00d..c5b90a309685 100644
--- a/net/core/lwt_bpf.c
+++ b/net/core/lwt_bpf.c
@@ -246,8 +246,10 @@ static int bpf_lwt_xmit_reroute(struct sk_buff *skb)
* if there is enough header space in skb.
*/
err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
- if (unlikely(err))
+ if (unlikely(err)) {
+ dst_release(dst);
goto err;
+ }
skb_dst_drop(skb);
skb_dst_set(skb, dst);
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index a7fa17b6a129..1c82146b5079 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -741,7 +741,7 @@ static __net_init int sysctl_core_net_init(struct net *net)
static __net_exit void sysctl_core_net_exit(struct net *net)
{
- struct ctl_table *tbl;
+ const struct ctl_table *tbl;
tbl = net->core.sysctl_hdr->ctl_table_arg;
unregister_net_sysctl_table(net->core.sysctl_hdr);
diff --git a/net/ieee802154/6lowpan/reassembly.c b/net/ieee802154/6lowpan/reassembly.c
index ba0455ad7701..26506dd4b357 100644
--- a/net/ieee802154/6lowpan/reassembly.c
+++ b/net/ieee802154/6lowpan/reassembly.c
@@ -399,7 +399,7 @@ static int __net_init lowpan_frags_ns_sysctl_register(struct net *net)
static void __net_exit lowpan_frags_ns_sysctl_unregister(struct net *net)
{
- struct ctl_table *table;
+ const struct ctl_table *table;
struct netns_ieee802154_lowpan *ieee802154_lowpan =
net_ieee802154_lowpan(net);
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 798497c8b192..5d0994ee3409 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -2793,7 +2793,7 @@ static __net_init int devinet_init_net(struct net *net)
static __net_exit void devinet_exit_net(struct net *net)
{
#ifdef CONFIG_SYSCTL
- struct ctl_table *tbl;
+ const struct ctl_table *tbl;
tbl = net->ipv4.forw_hdr->ctl_table_arg;
unregister_net_sysctl_table(net->ipv4.forw_hdr);
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 786e761bd0a1..66bd7e29f4c7 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -632,7 +632,7 @@ static int __net_init ip4_frags_ns_ctl_register(struct net *net)
static void __net_exit ip4_frags_ns_ctl_unregister(struct net *net)
{
- struct ctl_table *table;
+ const struct ctl_table *table;
table = net->ipv4.frags_hdr->ctl_table_arg;
unregister_net_sysctl_table(net->ipv4.frags_hdr);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index f134c59f839e..87eaae03e618 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -902,8 +902,6 @@ void ip_rt_send_redirect(struct sk_buff *skb)
peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr, vif);
if (!peer) {
rcu_read_unlock();
- icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST,
- rt_nexthop(rt, ip_hdr(skb)->daddr));
return;
}
@@ -3623,7 +3621,7 @@ static __net_init int sysctl_route_net_init(struct net *net)
static __net_exit void sysctl_route_net_exit(struct net *net)
{
- struct ctl_table *tbl;
+ const struct ctl_table *tbl;
tbl = net->ipv4.route_hdr->ctl_table_arg;
unregister_net_sysctl_table(net->ipv4.route_hdr);
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 47f2a00e457d..ff849a5b863e 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -1564,7 +1564,7 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)
static __net_exit void ipv4_sysctl_exit_net(struct net *net)
{
- struct ctl_table *table;
+ const struct ctl_table *table;
table = net->ipv4.ipv4_hdr->ctl_table_arg;
unregister_net_sysctl_table(net->ipv4.ipv4_hdr);
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 63bbc7f6a5a8..96fd07ce5a36 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -182,7 +182,7 @@ static __net_init int xfrm4_net_sysctl_init(struct net *net)
static __net_exit void xfrm4_net_sysctl_exit(struct net *net)
{
- struct ctl_table *table;
+ const struct ctl_table *table;
if (!net->ipv4.xfrm4_hdr)
return;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 83dc90a8990c..048ce7fb57fd 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -7251,7 +7251,7 @@ static int __addrconf_sysctl_register(struct net *net, char *dev_name,
static void __addrconf_sysctl_unregister(struct net *net,
struct ipv6_devconf *p, int ifindex)
{
- struct ctl_table *table;
+ const struct ctl_table *table;
if (!p->sysctl_header)
return;
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index e0f0c5f8cccd..2fd020e868c1 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -301,6 +301,7 @@ INDIRECT_CALLABLE_SCOPE bool fib6_rule_suppress(struct fib_rule *rule,
suppress_route:
ip6_rt_put_flags(rt, flags);
+ res->rt6 = NULL;
return true;
}
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 7a28807ca446..383b07269a49 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -627,11 +627,11 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
const struct nlmsghdr *nlh = cb->nlh;
struct net *net = sock_net(skb->sk);
unsigned int h, s_h;
- unsigned int e = 0, s_e;
struct fib6_walker *w;
struct fib6_table *tb;
struct hlist_head *head;
int res = 0;
+ u32 s_id;
if (cb->strict_check) {
int err;
@@ -689,25 +689,24 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
}
s_h = cb->args[0];
- s_e = cb->args[1];
+ s_id = cb->args[1];
rcu_read_lock();
- for (h = s_h; h < FIB6_TABLE_HASHSZ; h++, s_e = 0) {
- e = 0;
+ for (h = s_h; h < FIB6_TABLE_HASHSZ; h++, s_id = 0) {
head = &net->ipv6.fib_table_hash[h];
hlist_for_each_entry_rcu(tb, head, tb6_hlist) {
- if (e < s_e)
- goto next;
+ if (s_id && tb->tb6_id != s_id)
+ continue;
+
+ s_id = 0;
+ cb->args[1] = tb->tb6_id;
res = fib6_dump_table(tb, skb, cb);
if (res != 0)
goto out_unlock;
-next:
- e++;
}
}
out_unlock:
rcu_read_unlock();
- cb->args[1] = e;
cb->args[0] = h;
out:
res = res < 0 ? res : skb->len;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 2e2cd0e0d48a..5ee625d81942 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -625,7 +625,7 @@ int ip6_forward(struct sk_buff *skb)
/* Limit redirects both by destination (here)
and by source (inside ndisc_send_redirect)
*/
- if (inet_peer_xrlim_allow(peer, 1*HZ))
+ if (peer && inet_peer_xrlim_allow(peer, 1*HZ))
ndisc_send_redirect(skb, target);
rcu_read_unlock();
} else {
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 342e7066f765..8adb31804f01 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1731,6 +1731,8 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
rcu_read_lock();
peer = inet_getpeer_v6(net->ipv6.peers, &ipv6_hdr(skb)->saddr);
+ if (!peer)
+ goto release;
ret = inet_peer_xrlim_allow(peer, 1*HZ);
rcu_read_unlock();
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 18e0e1c76c1e..aee6d8eee8c9 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -105,7 +105,7 @@ static int nf_ct_frag6_sysctl_register(struct net *net)
static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net)
{
struct nft_ct_frag6_pernet *nf_frag = nf_frag_pernet(net);
- struct ctl_table *table;
+ const struct ctl_table *table;
table = nf_frag->nf_frag_frags_hdr->ctl_table_arg;
unregister_net_sysctl_table(nf_frag->nf_frag_frags_hdr);
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index cb219d4bdf25..225a23f7fefa 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -487,7 +487,7 @@ static int __net_init ip6_frags_ns_sysctl_register(struct net *net)
static void __net_exit ip6_frags_ns_sysctl_unregister(struct net *net)
{
- struct ctl_table *table;
+ const struct ctl_table *table;
table = net->ipv6.sysctl.frags_hdr->ctl_table_arg;
unregister_net_sysctl_table(net->ipv6.sysctl.frags_hdr);
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index 888676163e90..75de55f907b0 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -313,9 +313,9 @@ static int __net_init ipv6_sysctl_net_init(struct net *net)
static void __net_exit ipv6_sysctl_net_exit(struct net *net)
{
- struct ctl_table *ipv6_table;
- struct ctl_table *ipv6_route_table;
- struct ctl_table *ipv6_icmp_table;
+ const struct ctl_table *ipv6_table;
+ const struct ctl_table *ipv6_route_table;
+ const struct ctl_table *ipv6_icmp_table;
ipv6_table = net->ipv6.sysctl.hdr->ctl_table_arg;
ipv6_route_table = net->ipv6.sysctl.route_hdr->ctl_table_arg;
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 6bf22fd9cd38..cf31d884fa58 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -229,7 +229,7 @@ static int __net_init xfrm6_net_sysctl_init(struct net *net)
static void __net_exit xfrm6_net_sysctl_exit(struct net *net)
{
- struct ctl_table *table;
+ const struct ctl_table *table;
if (!net->ipv6.sysctl.xfrm6_hdr)
return;
diff --git a/net/mac80211/s1g.c b/net/mac80211/s1g.c
index c1f964e9991c..9914390ff31f 100644
--- a/net/mac80211/s1g.c
+++ b/net/mac80211/s1g.c
@@ -100,6 +100,10 @@ ieee80211_s1g_rx_twt_setup(struct ieee80211_sub_if_data *sdata,
struct ieee80211_twt_setup *twt = (void *)mgmt->u.action.u.s1g.variable;
struct ieee80211_twt_params *twt_agrt = (void *)twt->params;
+ if (!(twt->control & IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST) &&
+ twt->length < sizeof(twt->control) + sizeof(*twt_agrt))
+ return;
+
twt_agrt->req_type &= cpu_to_le16(~IEEE80211_TWT_REQTYPE_REQUEST);
/* broadcast TWT not supported yet */
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index 2099ce095edc..73e44f9e58c3 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -1422,7 +1422,7 @@ static void mpls_dev_sysctl_unregister(struct net_device *dev,
struct mpls_dev *mdev)
{
struct net *net = dev_net(dev);
- struct ctl_table *table;
+ const struct ctl_table *table;
if (!mdev->sysctl)
return;
@@ -2469,6 +2469,7 @@ static int mpls_getroute(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
r->rtm_family = AF_MPLS;
r->rtm_dst_len = 20;
r->rtm_src_len = 0;
+ r->rtm_tos = 0;
r->rtm_table = RT_TABLE_MAIN;
r->rtm_type = RTN_UNICAST;
r->rtm_scope = RT_SCOPE_UNIVERSE;
@@ -2691,7 +2692,7 @@ static void mpls_net_exit(struct net *net)
{
struct mpls_route __rcu **platform_label;
size_t platform_labels;
- struct ctl_table *table;
+ const struct ctl_table *table;
unsigned int index;
table = net->mpls.ctl->ctl_table_arg;
diff --git a/net/mptcp/ctrl.c b/net/mptcp/ctrl.c
index 34ae0ef4f9f3..d430f3d4af36 100644
--- a/net/mptcp/ctrl.c
+++ b/net/mptcp/ctrl.c
@@ -218,7 +218,7 @@ static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet)
static void mptcp_pernet_del_table(struct mptcp_pernet *pernet)
{
- struct ctl_table *table = pernet->ctl_table_hdr->ctl_table_arg;
+ const struct ctl_table *table = pernet->ctl_table_hdr->ctl_table_arg;
unregister_net_sysctl_table(pernet->ctl_table_hdr);
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index a92b1d0fee19..0d21f4e69390 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -428,7 +428,7 @@ bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
{
- struct mptcp_addr_info skc_local;
+ struct mptcp_pm_addr_entry skc_local = { 0 };
struct mptcp_addr_info msk_local;
if (WARN_ON_ONCE(!msk))
@@ -438,10 +438,13 @@ int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
* addr
*/
mptcp_local_address((struct sock_common *)msk, &msk_local);
- mptcp_local_address((struct sock_common *)skc, &skc_local);
- if (mptcp_addresses_equal(&msk_local, &skc_local, false))
+ mptcp_local_address((struct sock_common *)skc, &skc_local.addr);
+ if (mptcp_addresses_equal(&msk_local, &skc_local.addr, false))
return 0;
+ skc_local.addr.id = 0;
+ skc_local.flags = MPTCP_PM_ADDR_FLAG_IMPLICIT;
+
if (mptcp_pm_is_userspace(msk))
return mptcp_userspace_pm_get_local_id(msk, &skc_local);
return mptcp_pm_nl_get_local_id(msk, &skc_local);
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
index 74ec7ecf4e8f..242011de052a 100644
--- a/net/mptcp/pm_netlink.c
+++ b/net/mptcp/pm_netlink.c
@@ -1277,21 +1277,18 @@ static int mptcp_pm_nl_create_listen_socket(struct sock *sk,
return err;
}
-int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc)
+int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk,
+ struct mptcp_pm_addr_entry *skc)
{
struct mptcp_pm_addr_entry *entry;
struct pm_nl_pernet *pernet;
- int ret = -1;
+ int ret;
pernet = pm_nl_get_pernet_from_msk(msk);
rcu_read_lock();
- list_for_each_entry_rcu(entry, &pernet->local_addr_list, list) {
- if (mptcp_addresses_equal(&entry->addr, skc, entry->addr.port)) {
- ret = entry->addr.id;
- break;
- }
- }
+ entry = __lookup_addr(pernet, &skc->addr);
+ ret = entry ? entry->addr.id : -1;
rcu_read_unlock();
if (ret >= 0)
return ret;
@@ -1301,12 +1298,8 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc
if (!entry)
return -ENOMEM;
- entry->addr = *skc;
- entry->addr.id = 0;
+ *entry = *skc;
entry->addr.port = 0;
- entry->ifindex = 0;
- entry->flags = MPTCP_PM_ADDR_FLAG_IMPLICIT;
- entry->lsk = NULL;
ret = mptcp_pm_nl_append_new_local_addr(pernet, entry, false);
if (ret < 0)
kfree(entry);
@@ -1318,15 +1311,11 @@ bool mptcp_pm_nl_is_backup(struct mptcp_sock *msk, struct mptcp_addr_info *skc)
{
struct pm_nl_pernet *pernet = pm_nl_get_pernet_from_msk(msk);
struct mptcp_pm_addr_entry *entry;
- bool backup = false;
+ bool backup;
rcu_read_lock();
- list_for_each_entry_rcu(entry, &pernet->local_addr_list, list) {
- if (mptcp_addresses_equal(&entry->addr, skc, entry->addr.port)) {
- backup = !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP);
- break;
- }
- }
+ entry = __lookup_addr(pernet, skc);
+ backup = entry && !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP);
rcu_read_unlock();
return backup;
diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c
index 663aeefbd1b2..ded7a4d41691 100644
--- a/net/mptcp/pm_userspace.c
+++ b/net/mptcp/pm_userspace.c
@@ -25,6 +25,19 @@ void mptcp_free_local_addr_list(struct mptcp_sock *msk)
}
}
+static struct mptcp_pm_addr_entry *
+mptcp_userspace_pm_lookup_addr(struct mptcp_sock *msk,
+ const struct mptcp_addr_info *addr)
+{
+ struct mptcp_pm_addr_entry *entry;
+
+ list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) {
+ if (mptcp_addresses_equal(&entry->addr, addr, false))
+ return entry;
+ }
+ return NULL;
+}
+
static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
struct mptcp_pm_addr_entry *entry,
bool needs_id)
@@ -89,22 +102,20 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
static int mptcp_userspace_pm_delete_local_addr(struct mptcp_sock *msk,
struct mptcp_pm_addr_entry *addr)
{
- struct mptcp_pm_addr_entry *entry, *tmp;
struct sock *sk = (struct sock *)msk;
+ struct mptcp_pm_addr_entry *entry;
- list_for_each_entry_safe(entry, tmp, &msk->pm.userspace_pm_local_addr_list, list) {
- if (mptcp_addresses_equal(&entry->addr, &addr->addr, false)) {
- /* TODO: a refcount is needed because the entry can
- * be used multiple times (e.g. fullmesh mode).
- */
- list_del_rcu(&entry->list);
- sock_kfree_s(sk, entry, sizeof(*entry));
- msk->pm.local_addr_used--;
- return 0;
- }
- }
+ entry = mptcp_userspace_pm_lookup_addr(msk, &addr->addr);
+ if (!entry)
+ return -EINVAL;
- return -EINVAL;
+ /* TODO: a refcount is needed because the entry can
+ * be used multiple times (e.g. fullmesh mode).
+ */
+ list_del_rcu(&entry->list);
+ sock_kfree_s(sk, entry, sizeof(*entry));
+ msk->pm.local_addr_used--;
+ return 0;
}
static struct mptcp_pm_addr_entry *
@@ -137,47 +148,36 @@ int mptcp_userspace_pm_get_flags_and_ifindex_by_id(struct mptcp_sock *msk,
}
int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk,
- struct mptcp_addr_info *skc)
+ struct mptcp_pm_addr_entry *skc)
{
- struct mptcp_pm_addr_entry *entry = NULL, *e, new_entry;
__be16 msk_sport = ((struct inet_sock *)
inet_sk((struct sock *)msk))->inet_sport;
+ struct mptcp_pm_addr_entry *entry;
+ int id;
spin_lock_bh(&msk->pm.lock);
- list_for_each_entry(e, &msk->pm.userspace_pm_local_addr_list, list) {
- if (mptcp_addresses_equal(&e->addr, skc, false)) {
- entry = e;
- break;
- }
- }
+ entry = mptcp_userspace_pm_lookup_addr(msk, &skc->addr);
+ id = entry ? entry->addr.id : -1;
spin_unlock_bh(&msk->pm.lock);
- if (entry)
- return entry->addr.id;
- memset(&new_entry, 0, sizeof(struct mptcp_pm_addr_entry));
- new_entry.addr = *skc;
- new_entry.addr.id = 0;
- new_entry.flags = MPTCP_PM_ADDR_FLAG_IMPLICIT;
+ if (id != -1)
+ return id;
- if (new_entry.addr.port == msk_sport)
- new_entry.addr.port = 0;
+ if (skc->addr.port == msk_sport)
+ skc->addr.port = 0;
- return mptcp_userspace_pm_append_new_local_addr(msk, &new_entry, true);
+ return mptcp_userspace_pm_append_new_local_addr(msk, skc, true);
}
bool mptcp_userspace_pm_is_backup(struct mptcp_sock *msk,
struct mptcp_addr_info *skc)
{
struct mptcp_pm_addr_entry *entry;
- bool backup = false;
+ bool backup;
spin_lock_bh(&msk->pm.lock);
- list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) {
- if (mptcp_addresses_equal(&entry->addr, skc, false)) {
- backup = !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP);
- break;
- }
- }
+ entry = mptcp_userspace_pm_lookup_addr(msk, skc);
+ backup = entry && !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP);
spin_unlock_bh(&msk->pm.lock);
return backup;
@@ -591,13 +591,12 @@ int mptcp_userspace_pm_set_flags(struct net *net, struct nlattr *token,
goto set_flags_err;
spin_lock_bh(&msk->pm.lock);
- list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) {
- if (mptcp_addresses_equal(&entry->addr, &loc->addr, false)) {
- if (bkup)
- entry->flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
- else
- entry->flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP;
- }
+ entry = mptcp_userspace_pm_lookup_addr(msk, &loc->addr);
+ if (entry) {
+ if (bkup)
+ entry->flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
+ else
+ entry->flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP;
}
spin_unlock_bh(&msk->pm.lock);
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 48e1a3f853d3..251a1ad71ebb 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -1048,8 +1048,10 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int opt_size,
bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining,
struct mptcp_rm_list *rm_list);
int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
-int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc);
-int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc);
+int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk,
+ struct mptcp_pm_addr_entry *skc);
+int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk,
+ struct mptcp_pm_addr_entry *skc);
bool mptcp_pm_is_backup(struct mptcp_sock *msk, struct sock_common *skc);
bool mptcp_pm_nl_is_backup(struct mptcp_sock *msk, struct mptcp_addr_info *skc);
bool mptcp_userspace_pm_is_backup(struct mptcp_sock *msk, struct mptcp_addr_info *skc);
diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h
index ad2ff9cc0b58..81ad6747bc7a 100644
--- a/net/netfilter/ipset/ip_set_hash_gen.h
+++ b/net/netfilter/ipset/ip_set_hash_gen.h
@@ -983,7 +983,7 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
#endif
if (SET_WITH_COUNTER(set))
ip_set_init_counter(ext_counter(data, set), ext);
- if (SET_WITH_COMMENT(set))
+ if (SET_WITH_COMMENT(set) && !ext->target)
ip_set_init_comment(set, ext_comment(data, set), ext);
if (SET_WITH_SKBINFO(set))
ip_set_init_skbinfo(ext_skbinfo(data, set), ext);
diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c
index f9132b359f0c..0c690a30a85d 100644
--- a/net/netfilter/ipvs/ip_vs_app.c
+++ b/net/netfilter/ipvs/ip_vs_app.c
@@ -368,7 +368,7 @@ static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff *skb,
if (skb_ensure_writable(skb, ipvsh->len + sizeof(*th)))
return 0;
- th = (struct tcphdr *)(skb_network_header(skb) + ipvsh->len);
+ th = (struct tcphdr *)(skb->data + ipvsh->len);
/*
* Remember seq number in case this pkt gets resized
@@ -444,7 +444,7 @@ static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb,
if (skb_ensure_writable(skb, ipvsh->len + sizeof(*th)))
return 0;
- th = (struct tcphdr *)(skb_network_header(skb) + ipvsh->len);
+ th = (struct tcphdr *)(skb->data + ipvsh->len);
/*
* Remember seq number in case this pkt gets resized
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index 9636478e0284..811552669dac 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -598,6 +598,9 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest)
flags = cp->flags;
/* Bind with the destination and its corresponding transmitter */
if (flags & IP_VS_CONN_F_SYNC) {
+ /* Synced conns are hashed, so they can not get this flag */
+ conn_flags &= ~IP_VS_CONN_F_ONE_PACKET;
+
/* if the connection is not template and is created
* by sync, preserve the activity flag.
*/
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index fcd8e0857de2..e49a4840effb 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -689,7 +689,7 @@ static int sysctl_nat_icmp_send(struct netns_ipvs *ipvs) { return 0; }
#endif
-__sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset)
+static __sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset)
{
return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0));
}
@@ -746,13 +746,13 @@ static int ip_vs_route_me_harder(struct netns_ipvs *ipvs, int af,
* - inout: 1=in->out, 0=out->in
*/
void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
- struct ip_vs_conn *cp, int inout)
+ struct ip_vs_conn *cp, int inout, unsigned int toff,
+ bool has_ports)
{
struct iphdr *iph = ip_hdr(skb);
- unsigned int icmp_offset = iph->ihl*4;
- struct icmphdr *icmph = (struct icmphdr *)(skb_network_header(skb) +
- icmp_offset);
+ struct icmphdr *icmph = (struct icmphdr *)(skb->data + toff);
struct iphdr *ciph = (struct iphdr *)(icmph + 1);
+ unsigned int coff __maybe_unused = toff + sizeof(struct icmphdr);
if (inout) {
iph->saddr = cp->vaddr.ip;
@@ -767,8 +767,7 @@ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
}
/* the TCP/UDP/SCTP port */
- if (IPPROTO_TCP == ciph->protocol || IPPROTO_UDP == ciph->protocol ||
- IPPROTO_SCTP == ciph->protocol) {
+ if (has_ports) {
__be16 *ports = (void *)ciph + ciph->ihl*4;
if (inout)
@@ -779,48 +778,40 @@ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
/* And finally the ICMP checksum */
icmph->checksum = 0;
- icmph->checksum = ip_vs_checksum_complete(skb, icmp_offset);
+ icmph->checksum = ip_vs_checksum_complete(skb, toff);
skb->ip_summed = CHECKSUM_UNNECESSARY;
if (inout)
- IP_VS_DBG_PKT(11, AF_INET, pp, skb, (void *)ciph - (void *)iph,
- "Forwarding altered outgoing ICMP");
+ IP_VS_DBG_PKT(11, AF_INET, pp, skb, coff,
+ "Forwarding altered outgoing ICMP");
else
- IP_VS_DBG_PKT(11, AF_INET, pp, skb, (void *)ciph - (void *)iph,
- "Forwarding altered incoming ICMP");
+ IP_VS_DBG_PKT(11, AF_INET, pp, skb, coff,
+ "Forwarding altered incoming ICMP");
}
#ifdef CONFIG_IP_VS_IPV6
void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp,
- struct ip_vs_conn *cp, int inout)
+ struct ip_vs_conn *cp, int inout, unsigned int toff,
+ bool has_ports, struct ip_vs_iphdr *ciph)
{
struct ipv6hdr *iph = ipv6_hdr(skb);
- unsigned int icmp_offset = 0;
- unsigned int offs = 0; /* header offset*/
- int protocol;
struct icmp6hdr *icmph;
- struct ipv6hdr *ciph;
- unsigned short fragoffs;
+ struct ipv6hdr *cih;
- ipv6_find_hdr(skb, &icmp_offset, IPPROTO_ICMPV6, &fragoffs, NULL);
- icmph = (struct icmp6hdr *)(skb_network_header(skb) + icmp_offset);
- offs = icmp_offset + sizeof(struct icmp6hdr);
- ciph = (struct ipv6hdr *)(skb_network_header(skb) + offs);
-
- protocol = ipv6_find_hdr(skb, &offs, -1, &fragoffs, NULL);
+ icmph = (struct icmp6hdr *)(skb->data + toff);
+ cih = (struct ipv6hdr *)(skb->data + ciph->off);
if (inout) {
iph->saddr = cp->vaddr.in6;
- ciph->daddr = cp->vaddr.in6;
+ cih->daddr = cp->vaddr.in6;
} else {
iph->daddr = cp->daddr.in6;
- ciph->saddr = cp->daddr.in6;
+ cih->saddr = cp->daddr.in6;
}
/* the TCP/UDP/SCTP port */
- if (!fragoffs && (IPPROTO_TCP == protocol || IPPROTO_UDP == protocol ||
- IPPROTO_SCTP == protocol)) {
- __be16 *ports = (void *)(skb_network_header(skb) + offs);
+ if (has_ports) {
+ __be16 *ports = (void *)(skb->data + ciph->len);
IP_VS_DBG(11, "%s() changed port %d to %d\n", __func__,
ntohs(inout ? ports[1] : ports[0]),
@@ -833,19 +824,17 @@ void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp,
/* And finally the ICMP checksum */
icmph->icmp6_cksum = ~csum_ipv6_magic(&iph->saddr, &iph->daddr,
- skb->len - icmp_offset,
+ skb->len - toff,
IPPROTO_ICMPV6, 0);
- skb->csum_start = skb_network_header(skb) - skb->head + icmp_offset;
+ skb->csum_start = skb_headroom(skb) + toff;
skb->csum_offset = offsetof(struct icmp6hdr, icmp6_cksum);
skb->ip_summed = CHECKSUM_PARTIAL;
if (inout)
- IP_VS_DBG_PKT(11, AF_INET6, pp, skb,
- (void *)ciph - (void *)iph,
+ IP_VS_DBG_PKT(11, AF_INET6, pp, skb, ciph->off,
"Forwarding altered outgoing ICMPv6");
else
- IP_VS_DBG_PKT(11, AF_INET6, pp, skb,
- (void *)ciph - (void *)iph,
+ IP_VS_DBG_PKT(11, AF_INET6, pp, skb, ciph->off,
"Forwarding altered incoming ICMPv6");
}
#endif
@@ -855,36 +844,41 @@ void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp,
*/
static int handle_response_icmp(int af, struct sk_buff *skb,
union nf_inet_addr *snet,
- __u8 protocol, struct ip_vs_conn *cp,
+ struct ip_vs_conn *cp,
struct ip_vs_protocol *pp,
- unsigned int offset, unsigned int ihl,
- unsigned int hooknum)
+ struct ip_vs_iphdr *ciph,
+ unsigned int toff, unsigned int hooknum)
{
+ int iproto = af == AF_INET6 ? IPPROTO_ICMPV6 : IPPROTO_ICMP;
unsigned int verdict = NF_DROP;
+ unsigned int ctoff = ciph->len;
+ bool has_ports = false;
if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)
goto after_nat;
/* Ensure the checksum is correct */
- if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) {
+ if (!ip_vs_checksum_common_check(skb, toff, iproto, af)) {
/* Failed checksum! */
IP_VS_DBG_BUF(1, "Forward ICMP: failed checksum from %s!\n",
IP_VS_DBG_ADDR(af, snet));
goto out;
}
- if (IPPROTO_TCP == protocol || IPPROTO_UDP == protocol ||
- IPPROTO_SCTP == protocol)
- offset += 2 * sizeof(__u16);
- if (skb_ensure_writable(skb, offset))
+ if (ciph->protocol == IPPROTO_TCP || ciph->protocol == IPPROTO_UDP ||
+ ciph->protocol == IPPROTO_SCTP) {
+ ctoff += 2 * sizeof(__u16);
+ has_ports = true;
+ }
+ if (skb_ensure_writable(skb, ctoff))
goto out;
#ifdef CONFIG_IP_VS_IPV6
if (af == AF_INET6)
- ip_vs_nat_icmp_v6(skb, pp, cp, 1);
+ ip_vs_nat_icmp_v6(skb, pp, cp, 1, toff, has_ports, ciph);
else
#endif
- ip_vs_nat_icmp(skb, pp, cp, 1);
+ ip_vs_nat_icmp(skb, pp, cp, 1, toff, has_ports);
if (ip_vs_route_me_harder(cp->ipvs, af, skb, hooknum))
goto out;
@@ -912,9 +906,9 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
* Currently handles error types - unreachable, quench, ttl exceeded.
*/
static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
- int *related, unsigned int hooknum)
+ int *related, unsigned int hooknum,
+ struct ip_vs_iphdr *ipvsh)
{
- struct iphdr *iph;
struct icmphdr _icmph, *ic;
struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */
struct ip_vs_iphdr ciph;
@@ -929,17 +923,19 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
if (ip_is_fragment(ip_hdr(skb))) {
if (ip_vs_gather_frags(ipvs, skb, ip_vs_defrag_user(hooknum)))
return NF_STOLEN;
+ if (!ip_vs_fill_iph_skb(AF_INET, skb, false, ipvsh))
+ return NF_ACCEPT;
}
- iph = ip_hdr(skb);
- offset = ihl = iph->ihl * 4;
+ ihl = ipvsh->len;
+ offset = ipvsh->len;
ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
if (ic == NULL)
return NF_DROP;
IP_VS_DBG(12, "Outgoing ICMP (%d,%d) %pI4->%pI4\n",
ic->type, ntohs(icmp_id(ic)),
- &iph->saddr, &iph->daddr);
+ &ipvsh->saddr.ip, &ipvsh->daddr.ip);
/*
* Work through seeing if this is for us.
@@ -958,7 +954,7 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
/* Now find the contained IP header */
offset += sizeof(_icmph);
cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
- if (cih == NULL)
+ if (!(cih && cih->version == 4 && cih->ihl >= 5))
return NF_ACCEPT; /* The packet looks wrong, ignore */
pp = ip_vs_proto_get(cih->protocol);
@@ -966,8 +962,7 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
return NF_ACCEPT;
/* Is the embedded protocol header present? */
- if (unlikely(cih->frag_off & htons(IP_OFFSET) &&
- pp->dont_defrag))
+ if (unlikely(cih->frag_off & htons(IP_OFFSET) && !pp->dont_defrag))
return NF_ACCEPT;
IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset,
@@ -981,9 +976,9 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
if (!cp)
return NF_ACCEPT;
- snet.ip = iph->saddr;
- return handle_response_icmp(AF_INET, skb, &snet, cih->protocol, cp,
- pp, ciph.len, ihl, hooknum);
+ snet.ip = ipvsh->saddr.ip;
+ return handle_response_icmp(AF_INET, skb, &snet, cp, pp, &ciph, ihl,
+ hooknum);
}
#ifdef CONFIG_IP_VS_IPV6
@@ -996,7 +991,6 @@ static int ip_vs_out_icmp_v6(struct netns_ipvs *ipvs, struct sk_buff *skb,
struct ip_vs_conn *cp;
struct ip_vs_protocol *pp;
union nf_inet_addr snet;
- unsigned int offset;
*related = 1;
ic = frag_safe_skb_hp(skb, ipvsh->len, sizeof(_icmph), &_icmph);
@@ -1032,6 +1026,10 @@ static int ip_vs_out_icmp_v6(struct netns_ipvs *ipvs, struct sk_buff *skb,
if (!pp)
return NF_ACCEPT;
+ /* Is the embedded protocol header present? */
+ if (unlikely(ciph.fragoffs && !pp->dont_defrag))
+ return NF_ACCEPT;
+
/* The embedded headers contain source and dest in reverse order */
cp = INDIRECT_CALL_1(pp->conn_out_get, ip_vs_conn_out_get_proto,
ipvs, AF_INET6, skb, &ciph);
@@ -1039,9 +1037,8 @@ static int ip_vs_out_icmp_v6(struct netns_ipvs *ipvs, struct sk_buff *skb,
return NF_ACCEPT;
snet.in6 = ciph.saddr.in6;
- offset = ciph.len;
- return handle_response_icmp(AF_INET6, skb, &snet, ciph.protocol, cp,
- pp, offset, ipvsh->len, hooknum);
+ return handle_response_icmp(AF_INET6, skb, &snet, cp, pp, &ciph,
+ ipvsh->len, hooknum);
}
#endif
@@ -1367,7 +1364,8 @@ ip_vs_out_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *stat
#endif
if (unlikely(iph.protocol == IPPROTO_ICMP)) {
int related;
- int verdict = ip_vs_out_icmp(ipvs, skb, &related, hooknum);
+ int verdict = ip_vs_out_icmp(ipvs, skb, &related,
+ hooknum, &iph);
if (related)
return verdict;
@@ -1571,9 +1569,8 @@ static int ipvs_gre_decap(struct netns_ipvs *ipvs, struct sk_buff *skb,
*/
static int
ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
- unsigned int hooknum)
+ unsigned int hooknum, struct ip_vs_iphdr *iph)
{
- struct iphdr *iph;
struct icmphdr _icmph, *ic;
struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */
struct ip_vs_iphdr ciph;
@@ -1583,7 +1580,7 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
unsigned int offset, offset2, ihl, verdict;
bool tunnel, new_cp = false;
union nf_inet_addr *raddr;
- char *outer_proto = "IPIP";
+ char *outer_proto __maybe_unused = "IPIP";
unsigned int hlen_ipip;
int ulen = 0;
@@ -1593,17 +1590,19 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
if (ip_is_fragment(ip_hdr(skb))) {
if (ip_vs_gather_frags(ipvs, skb, ip_vs_defrag_user(hooknum)))
return NF_STOLEN;
+ if (!ip_vs_fill_iph_skb(AF_INET, skb, false, iph))
+ return NF_ACCEPT;
}
- iph = ip_hdr(skb);
- offset = ihl = iph->ihl * 4;
+ ihl = iph->len;
+ offset = iph->len;
ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
if (ic == NULL)
return NF_DROP;
IP_VS_DBG(12, "Incoming ICMP (%d,%d) %pI4->%pI4\n",
ic->type, ntohs(icmp_id(ic)),
- &iph->saddr, &iph->daddr);
+ &iph->saddr.ip, &iph->daddr.ip);
/*
* Work through seeing if this is for us.
@@ -1685,8 +1684,7 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
pp = pd->pp;
/* Is the embedded protocol header present? */
- if (unlikely(cih->frag_off & htons(IP_OFFSET) &&
- pp->dont_defrag))
+ if (unlikely(cih->frag_off & htons(IP_OFFSET) && !pp->dont_defrag))
return NF_ACCEPT;
IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset,
@@ -1694,7 +1692,6 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
offset2 = offset;
ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, !tunnel, &ciph);
- offset = ciph.len;
/* The embedded headers contain source and dest in reverse order.
* For IPIP/UDP/GRE tunnel this is error for request, not for reply.
@@ -1716,10 +1713,11 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
verdict = NF_DROP;
/* Ensure the checksum is correct */
- if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) {
+ if ((IP_VS_FWD_METHOD(cp) == IP_VS_CONN_F_MASQ || tunnel) &&
+ !ip_vs_checksum_common_check(skb, ihl, IPPROTO_ICMP, AF_INET)) {
/* Failed checksum! */
IP_VS_DBG(1, "Incoming ICMP: failed checksum from %pI4!\n",
- &iph->saddr);
+ &iph->saddr.ip);
goto out;
}
@@ -1787,10 +1785,7 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
/* do the statistics and put it back */
ip_vs_in_stats(cp, skb);
- if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol ||
- IPPROTO_SCTP == cih->protocol)
- offset += 2 * sizeof(__u16);
- verdict = ip_vs_icmp_xmit(skb, cp, pp, offset, hooknum, &ciph);
+ verdict = ip_vs_icmp_xmit(skb, cp, pp, iph->len, hooknum, &ciph);
out:
if (likely(!new_cp))
@@ -1850,8 +1845,8 @@ static int ip_vs_in_icmp_v6(struct netns_ipvs *ipvs, struct sk_buff *skb,
return NF_ACCEPT;
pp = pd->pp;
- /* Cannot handle fragmented embedded protocol */
- if (ciph.fragoffs)
+ /* Is the embedded protocol header present? */
+ if (ciph.fragoffs && !pp->dont_defrag)
return NF_ACCEPT;
IP_VS_DBG_PKT(11, AF_INET6, pp, skb, offset,
@@ -1875,23 +1870,22 @@ static int ip_vs_in_icmp_v6(struct netns_ipvs *ipvs, struct sk_buff *skb,
new_cp = true;
}
- /* VS/TUN, VS/DR and LOCALNODE just let it go */
- if ((hooknum == NF_INET_LOCAL_OUT) &&
- (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)) {
- verdict = NF_ACCEPT;
+ verdict = NF_DROP;
+
+ /* Ensure the checksum is correct */
+ if (IP_VS_FWD_METHOD(cp) == IP_VS_CONN_F_MASQ &&
+ !ip_vs_checksum_common_check(skb, iph->len, IPPROTO_ICMPV6,
+ AF_INET6)) {
+ /* Failed checksum! */
+ IP_VS_DBG(1, "Incoming ICMPv6: failed checksum from %pI6c!\n",
+ &iph->saddr);
goto out;
}
/* do the statistics and put it back */
ip_vs_in_stats(cp, skb);
- /* Need to mangle contained IPv6 header in ICMPv6 packet */
- offset = ciph.len;
- if (IPPROTO_TCP == ciph.protocol || IPPROTO_UDP == ciph.protocol ||
- IPPROTO_SCTP == ciph.protocol)
- offset += 2 * sizeof(__u16); /* Also mangle ports */
-
- verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset, hooknum, &ciph);
+ verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, iph->len, hooknum, &ciph);
out:
if (likely(!new_cp))
@@ -1970,7 +1964,7 @@ ip_vs_in_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state
if (unlikely(iph.protocol == IPPROTO_ICMP)) {
int related;
int verdict = ip_vs_in_icmp(ipvs, skb, &related,
- hooknum);
+ hooknum, &iph);
if (related)
return verdict;
@@ -2106,6 +2100,7 @@ ip_vs_forward_icmp(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
struct netns_ipvs *ipvs = net_ipvs(state->net);
+ struct ip_vs_iphdr iphdr;
int r;
/* ipvs enabled in this netns ? */
@@ -2115,10 +2110,9 @@ ip_vs_forward_icmp(void *priv, struct sk_buff *skb,
if (state->pf == NFPROTO_IPV4) {
if (ip_hdr(skb)->protocol != IPPROTO_ICMP)
return NF_ACCEPT;
+ ip_vs_fill_iph_skb(AF_INET, skb, false, &iphdr);
#ifdef CONFIG_IP_VS_IPV6
} else {
- struct ip_vs_iphdr iphdr;
-
ip_vs_fill_iph_skb(AF_INET6, skb, false, &iphdr);
if (iphdr.protocol != IPPROTO_ICMPV6)
@@ -2128,7 +2122,7 @@ ip_vs_forward_icmp(void *priv, struct sk_buff *skb,
#endif
}
- return ip_vs_in_icmp(ipvs, skb, &r, state->hook);
+ return ip_vs_in_icmp(ipvs, skb, &r, state->hook, &iphdr);
}
static const struct nf_hook_ops ip_vs_ops4[] = {
diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c
index c67317be17df..3dbd3096e163 100644
--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
@@ -11,7 +11,7 @@
static int
sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
- unsigned int sctphoff);
+ struct ip_vs_iphdr *iph);
static int
sctp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
@@ -109,7 +109,7 @@ sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
int ret;
/* Some checks before mangling */
- if (!sctp_csum_check(cp->af, skb, pp, sctphoff))
+ if (!sctp_csum_check(cp->af, skb, pp, iph))
return 0;
/* Call application helper if needed */
@@ -121,7 +121,7 @@ sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
payload_csum = true;
}
- sctph = (void *) skb_network_header(skb) + sctphoff;
+ sctph = (void *)skb->data + sctphoff;
/* Only update csum if we really have to */
if (sctph->source != cp->vport || payload_csum ||
@@ -157,7 +157,7 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
int ret;
/* Some checks before mangling */
- if (!sctp_csum_check(cp->af, skb, pp, sctphoff))
+ if (!sctp_csum_check(cp->af, skb, pp, iph))
return 0;
/* Call application helper if needed */
@@ -169,7 +169,7 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
payload_csum = true;
}
- sctph = (void *) skb_network_header(skb) + sctphoff;
+ sctph = (void *)skb->data + sctphoff;
/* Only update csum if we really have to */
if (sctph->dest != cp->dport || payload_csum ||
@@ -187,19 +187,22 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
static int
sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
- unsigned int sctphoff)
+ struct ip_vs_iphdr *iph)
{
+ unsigned int sctphoff = iph->len;
struct sctphdr *sh;
__le32 cmp, val;
+ if (!ip_vs_checksum_needed(skb, af))
+ return 1;
sh = (struct sctphdr *)(skb->data + sctphoff);
cmp = sh->checksum;
val = sctp_compute_cksum(skb, sctphoff);
if (val != cmp) {
/* CRC failure, dump it. */
- IP_VS_DBG_RL_PKT(0, af, pp, skb, 0,
- "Failed checksum for");
+ IP_VS_DBG_RL_PKT(0, af, pp, skb, iph->off,
+ "Failed checksum for");
return 0;
}
return 1;
diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c
index b382810156b2..1ac9c233537d 100644
--- a/net/netfilter/ipvs/ip_vs_proto_tcp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c
@@ -30,7 +30,7 @@
static int
tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
- unsigned int tcphoff);
+ struct ip_vs_iphdr *iph);
static int
tcp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
@@ -167,7 +167,7 @@ tcp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
int ret;
/* Some checks before mangling */
- if (!tcp_csum_check(cp->af, skb, pp, tcphoff))
+ if (!tcp_csum_check(cp->af, skb, pp, iph))
return 0;
/* Call application helper if needed */
@@ -180,7 +180,7 @@ tcp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
payload_csum = true;
}
- tcph = (void *)skb_network_header(skb) + tcphoff;
+ tcph = (void *)skb->data + tcphoff;
tcph->source = cp->vport;
/* Adjust TCP checksums */
@@ -245,7 +245,7 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
int ret;
/* Some checks before mangling */
- if (!tcp_csum_check(cp->af, skb, pp, tcphoff))
+ if (!tcp_csum_check(cp->af, skb, pp, iph))
return 0;
/*
@@ -261,7 +261,7 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
payload_csum = true;
}
- tcph = (void *)skb_network_header(skb) + tcphoff;
+ tcph = (void *)skb->data + tcphoff;
tcph->dest = cp->dport;
/*
@@ -303,41 +303,13 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
static int
tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
- unsigned int tcphoff)
+ struct ip_vs_iphdr *iph)
{
- switch (skb->ip_summed) {
- case CHECKSUM_NONE:
- skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0);
- fallthrough;
- case CHECKSUM_COMPLETE:
-#ifdef CONFIG_IP_VS_IPV6
- if (af == AF_INET6) {
- if (csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
- &ipv6_hdr(skb)->daddr,
- skb->len - tcphoff,
- IPPROTO_TCP,
- skb->csum)) {
- IP_VS_DBG_RL_PKT(0, af, pp, skb, 0,
- "Failed checksum for");
- return 0;
- }
- } else
-#endif
- if (csum_tcpudp_magic(ip_hdr(skb)->saddr,
- ip_hdr(skb)->daddr,
- skb->len - tcphoff,
- ip_hdr(skb)->protocol,
- skb->csum)) {
- IP_VS_DBG_RL_PKT(0, af, pp, skb, 0,
- "Failed checksum for");
- return 0;
- }
- break;
- default:
- /* No need to checksum. */
- break;
+ if (!ip_vs_checksum_common_check(skb, iph->len, IPPROTO_TCP, af)) {
+ IP_VS_DBG_RL_PKT(0, af, pp, skb, iph->off,
+ "Failed checksum for");
+ return 0;
}
-
return 1;
}
diff --git a/net/netfilter/ipvs/ip_vs_proto_udp.c b/net/netfilter/ipvs/ip_vs_proto_udp.c
index dbd4155bb075..96ac882df15c 100644
--- a/net/netfilter/ipvs/ip_vs_proto_udp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_udp.c
@@ -26,7 +26,7 @@
static int
udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
- unsigned int udphoff);
+ struct ip_vs_iphdr *iph);
static int
udp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
@@ -156,7 +156,7 @@ udp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
int ret;
/* Some checks before mangling */
- if (!udp_csum_check(cp->af, skb, pp, udphoff))
+ if (!udp_csum_check(cp->af, skb, pp, iph))
return 0;
/*
@@ -171,7 +171,7 @@ udp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
payload_csum = true;
}
- udph = (void *)skb_network_header(skb) + udphoff;
+ udph = (void *)skb->data + udphoff;
udph->source = cp->vport;
/*
@@ -239,7 +239,7 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
int ret;
/* Some checks before mangling */
- if (!udp_csum_check(cp->af, skb, pp, udphoff))
+ if (!udp_csum_check(cp->af, skb, pp, iph))
return 0;
/*
@@ -255,7 +255,7 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
payload_csum = true;
}
- udph = (void *)skb_network_header(skb) + udphoff;
+ udph = (void *)skb->data + udphoff;
udph->dest = cp->dport;
/*
@@ -299,48 +299,20 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
static int
udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
- unsigned int udphoff)
+ struct ip_vs_iphdr *iph)
{
struct udphdr _udph, *uh;
- uh = skb_header_pointer(skb, udphoff, sizeof(_udph), &_udph);
+ uh = skb_header_pointer(skb, iph->len, sizeof(_udph), &_udph);
if (uh == NULL)
return 0;
- if (uh->check != 0) {
- switch (skb->ip_summed) {
- case CHECKSUM_NONE:
- skb->csum = skb_checksum(skb, udphoff,
- skb->len - udphoff, 0);
- fallthrough;
- case CHECKSUM_COMPLETE:
-#ifdef CONFIG_IP_VS_IPV6
- if (af == AF_INET6) {
- if (csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
- &ipv6_hdr(skb)->daddr,
- skb->len - udphoff,
- IPPROTO_UDP,
- skb->csum)) {
- IP_VS_DBG_RL_PKT(0, af, pp, skb, 0,
- "Failed checksum for");
- return 0;
- }
- } else
-#endif
- if (csum_tcpudp_magic(ip_hdr(skb)->saddr,
- ip_hdr(skb)->daddr,
- skb->len - udphoff,
- ip_hdr(skb)->protocol,
- skb->csum)) {
- IP_VS_DBG_RL_PKT(0, af, pp, skb, 0,
- "Failed checksum for");
- return 0;
- }
- break;
- default:
- /* No need to checksum. */
- break;
- }
+ if (!uh->check)
+ return 1;
+ if (!ip_vs_checksum_common_check(skb, iph->len, IPPROTO_UDP, af)) {
+ IP_VS_DBG_RL_PKT(0, af, pp, skb, iph->off,
+ "Failed checksum for");
+ return 0;
}
return 1;
}
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 02a2a966911e..c214e5d05524 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -1473,20 +1473,22 @@ ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
*/
int
ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp, int offset, unsigned int hooknum,
- struct ip_vs_iphdr *iph)
+ struct ip_vs_protocol *pp, unsigned int toff,
+ unsigned int hooknum, struct ip_vs_iphdr *ciph)
{
struct rtable *rt; /* Route to the other host */
int rc;
int local;
int rt_mode, was_input;
+ bool has_ports = false;
+ unsigned int wlen;
/* The ICMP packet for VS/TUN, VS/DR and LOCALNODE will be
forwarded directly here, because there is no need to
translate address/port back */
if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) {
if (cp->packet_xmit)
- rc = cp->packet_xmit(skb, cp, pp, iph);
+ rc = cp->packet_xmit(skb, cp, pp, ciph);
else
rc = NF_ACCEPT;
/* do not touch skb anymore */
@@ -1504,7 +1506,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL |
IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL;
local = __ip_vs_get_out_rt(cp->ipvs, cp->af, skb, cp->dest, cp->daddr.ip, rt_mode,
- NULL, iph);
+ NULL, ciph);
if (local < 0)
goto tx_error;
rt = skb_rtable(skb);
@@ -1535,14 +1537,21 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
goto tx_error;
}
+ wlen = ciph->len;
+ if (ciph->protocol == IPPROTO_TCP || ciph->protocol == IPPROTO_UDP ||
+ ciph->protocol == IPPROTO_SCTP) {
+ wlen += 2 * sizeof(__u16); /* Also mangle ports */
+ has_ports = true;
+ }
+
/* copy-on-write the packet before mangling it */
- if (skb_ensure_writable(skb, offset))
+ if (skb_ensure_writable(skb, wlen))
goto tx_error;
if (skb_cow(skb, rt->dst.dev->hard_header_len))
goto tx_error;
- ip_vs_nat_icmp(skb, pp, cp, 0);
+ ip_vs_nat_icmp(skb, pp, cp, 0, toff, has_ports);
/* Another hack: avoid icmp_send in ip_fragment */
skb->ignore_df = 1;
@@ -1558,10 +1567,12 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
#ifdef CONFIG_IP_VS_IPV6
int
ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp, int offset, unsigned int hooknum,
- struct ip_vs_iphdr *ipvsh)
+ struct ip_vs_protocol *pp, unsigned int toff,
+ unsigned int hooknum, struct ip_vs_iphdr *ciph)
{
+ bool has_ports = false;
struct rt6_info *rt; /* Route to the other host */
+ unsigned int wlen;
int rc;
int local;
int rt_mode;
@@ -1571,7 +1582,7 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
translate address/port back */
if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) {
if (cp->packet_xmit)
- rc = cp->packet_xmit(skb, cp, pp, ipvsh);
+ rc = cp->packet_xmit(skb, cp, pp, ciph);
else
rc = NF_ACCEPT;
/* do not touch skb anymore */
@@ -1588,7 +1599,7 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL |
IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL;
local = __ip_vs_get_out_rt_v6(cp->ipvs, cp->af, skb, cp->dest,
- &cp->daddr.in6, NULL, ipvsh, 0, rt_mode);
+ &cp->daddr.in6, NULL, ciph, 0, rt_mode);
if (local < 0)
goto tx_error;
rt = dst_rt6_info(skb_dst(skb));
@@ -1619,14 +1630,21 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
goto tx_error;
}
+ wlen = ciph->len;
+ if (ciph->protocol == IPPROTO_TCP || ciph->protocol == IPPROTO_UDP ||
+ ciph->protocol == IPPROTO_SCTP) {
+ wlen += 2 * sizeof(__u16); /* Also mangle ports */
+ has_ports = true;
+ }
+
/* copy-on-write the packet before mangling it */
- if (skb_ensure_writable(skb, offset))
+ if (skb_ensure_writable(skb, wlen))
goto tx_error;
if (skb_cow(skb, rt->dst.dev->hard_header_len))
goto tx_error;
- ip_vs_nat_icmp_v6(skb, pp, cp, 0);
+ ip_vs_nat_icmp_v6(skb, pp, cp, 0, toff, has_ports, ciph);
/* Another hack: avoid icmp_send in ip_fragment */
skb->ignore_df = 1;
diff --git a/net/netfilter/nf_conntrack_broadcast.c b/net/netfilter/nf_conntrack_broadcast.c
index d44d9379a8a0..ef8a7ca8c116 100644
--- a/net/netfilter/nf_conntrack_broadcast.c
+++ b/net/netfilter/nf_conntrack_broadcast.c
@@ -72,6 +72,7 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb,
exp->flags = NF_CT_EXPECT_PERMANENT;
exp->class = NF_CT_EXPECT_CLASS_DEFAULT;
rcu_assign_pointer(exp->helper, helper);
+ rcu_assign_pointer(exp->assign_helper, NULL);
write_pnet(&exp->net, net);
#ifdef CONFIG_NF_CONNTRACK_ZONES
exp->zone = ct->zone;
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index b086670ec90d..bed9c370fd70 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1729,14 +1729,17 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
spin_lock_bh(&nf_conntrack_expect_lock);
exp = nf_ct_find_expectation(net, zone, tuple, !tmpl || nf_ct_is_confirmed(tmpl));
if (exp) {
+ struct nf_conntrack_helper *assign_helper;
+
/* Welcome, Mr. Bond. We've been expecting you... */
__set_bit(IPS_EXPECTED_BIT, &ct->status);
/* exp->master safe, refcnt bumped in nf_ct_find_expectation */
ct->master = exp->master;
- if (exp->helper) {
+ assign_helper = rcu_dereference(exp->assign_helper);
+ if (assign_helper) {
help = nf_ct_helper_ext_add(ct, GFP_ATOMIC);
if (help)
- rcu_assign_pointer(help->helper, exp->helper);
+ rcu_assign_pointer(help->helper, assign_helper);
}
#ifdef CONFIG_NF_CONNTRACK_MARK
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 379711ea5ab6..34324dece89d 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -344,6 +344,7 @@ void nf_ct_expect_init(struct nf_conntrack_expect *exp, unsigned int class,
helper = rcu_dereference(help->helper);
rcu_assign_pointer(exp->helper, helper);
+ rcu_assign_pointer(exp->assign_helper, NULL);
write_pnet(&exp->net, net);
#ifdef CONFIG_NF_CONNTRACK_ZONES
exp->zone = ct->zone;
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index 791aafe9f396..c42547284f35 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -642,7 +642,7 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
&ct->tuplehash[!dir].tuple.src.u3,
&ct->tuplehash[!dir].tuple.dst.u3,
IPPROTO_TCP, NULL, &port);
- rcu_assign_pointer(exp->helper, &nf_conntrack_helper_h245);
+ rcu_assign_pointer(exp->assign_helper, &nf_conntrack_helper_h245);
nathook = rcu_dereference(nfct_h323_nat_hook);
if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
@@ -766,7 +766,7 @@ static int expect_callforwarding(struct sk_buff *skb,
nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
&ct->tuplehash[!dir].tuple.src.u3, &addr,
IPPROTO_TCP, NULL, &port);
- rcu_assign_pointer(exp->helper, nf_conntrack_helper_q931);
+ rcu_assign_pointer(exp->assign_helper, nf_conntrack_helper_q931);
nathook = rcu_dereference(nfct_h323_nat_hook);
if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
@@ -1233,7 +1233,7 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
&ct->tuplehash[!dir].tuple.src.u3 : NULL,
&ct->tuplehash[!dir].tuple.dst.u3,
IPPROTO_TCP, NULL, &port);
- rcu_assign_pointer(exp->helper, nf_conntrack_helper_q931);
+ rcu_assign_pointer(exp->assign_helper, nf_conntrack_helper_q931);
exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple calls */
nathook = rcu_dereference(nfct_h323_nat_hook);
@@ -1305,7 +1305,7 @@ static int process_gcf(struct sk_buff *skb, struct nf_conn *ct,
nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
&ct->tuplehash[!dir].tuple.src.u3, &addr,
IPPROTO_UDP, NULL, &port);
- rcu_assign_pointer(exp->helper, nf_conntrack_helper_ras);
+ rcu_assign_pointer(exp->assign_helper, nf_conntrack_helper_ras);
if (nf_ct_expect_related(exp, 0) == 0) {
pr_debug("nf_ct_ras: expect RAS ");
@@ -1522,7 +1522,7 @@ static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
&ct->tuplehash[!dir].tuple.src.u3, &addr,
IPPROTO_TCP, NULL, &port);
exp->flags = NF_CT_EXPECT_PERMANENT;
- rcu_assign_pointer(exp->helper, nf_conntrack_helper_q931);
+ rcu_assign_pointer(exp->assign_helper, nf_conntrack_helper_q931);
if (nf_ct_expect_related(exp, 0) == 0) {
pr_debug("nf_ct_ras: expect Q.931 ");
@@ -1576,7 +1576,7 @@ static int process_lcf(struct sk_buff *skb, struct nf_conn *ct,
&ct->tuplehash[!dir].tuple.src.u3, &addr,
IPPROTO_TCP, NULL, &port);
exp->flags = NF_CT_EXPECT_PERMANENT;
- rcu_assign_pointer(exp->helper, nf_conntrack_helper_q931);
+ rcu_assign_pointer(exp->assign_helper, nf_conntrack_helper_q931);
if (nf_ct_expect_related(exp, 0) == 0) {
pr_debug("nf_ct_ras: expect Q.931 ");
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 1d449e825dc6..7174369e5aa6 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -424,6 +424,11 @@ static bool expect_iter_me(struct nf_conntrack_expect *exp, void *data)
this = rcu_dereference_protected(exp->helper,
lockdep_is_held(&nf_conntrack_expect_lock));
+ if (this == me)
+ return true;
+
+ this = rcu_dereference_protected(exp->assign_helper,
+ lockdep_is_held(&nf_conntrack_expect_lock));
return this == me;
}
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 1028ed8ac485..c9bbe25f2d67 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -2624,6 +2624,7 @@ static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
static struct nf_conntrack_expect *
ctnetlink_alloc_expect(const struct nlattr *const cda[], struct nf_conn *ct,
+ const struct nf_conntrack_helper *assign_helper,
struct nf_conntrack_tuple *tuple,
struct nf_conntrack_tuple *mask);
@@ -2850,6 +2851,7 @@ static int
ctnetlink_glue_attach_expect(const struct nlattr *attr, struct nf_conn *ct,
u32 portid, u32 report)
{
+ struct nf_conntrack_helper *assign_helper = NULL;
struct nlattr *cda[CTA_EXPECT_MAX+1];
struct nf_conntrack_tuple tuple, mask;
struct nf_conntrack_expect *exp;
@@ -2865,8 +2867,18 @@ ctnetlink_glue_attach_expect(const struct nlattr *attr, struct nf_conn *ct,
if (err < 0)
return err;
+ if (cda[CTA_EXPECT_HELP_NAME]) {
+ const char *helpname = nla_data(cda[CTA_EXPECT_HELP_NAME]);
+
+ assign_helper = __nf_conntrack_helper_find(helpname,
+ nf_ct_l3num(ct),
+ tuple.dst.protonum);
+ if (!assign_helper)
+ return -EOPNOTSUPP;
+ }
+
exp = ctnetlink_alloc_expect((const struct nlattr * const *)cda, ct,
- &tuple, &mask);
+ assign_helper, &tuple, &mask);
if (IS_ERR(exp))
return PTR_ERR(exp);
@@ -3505,6 +3517,7 @@ ctnetlink_parse_expect_nat(const struct nlattr *attr,
static struct nf_conntrack_expect *
ctnetlink_alloc_expect(const struct nlattr * const cda[], struct nf_conn *ct,
+ const struct nf_conntrack_helper *assign_helper,
struct nf_conntrack_tuple *tuple,
struct nf_conntrack_tuple *mask)
{
@@ -3558,6 +3571,7 @@ ctnetlink_alloc_expect(const struct nlattr * const cda[], struct nf_conn *ct,
exp->zone = ct->zone;
#endif
rcu_assign_pointer(exp->helper, helper);
+ rcu_assign_pointer(exp->assign_helper, assign_helper);
exp->tuple = *tuple;
exp->mask.src.u3 = mask->src.u3;
exp->mask.src.u.all = mask->src.u.all;
@@ -3613,7 +3627,7 @@ ctnetlink_create_expect(struct net *net,
ct = nf_ct_tuplehash_to_ctrack(h);
rcu_read_lock();
- exp = ctnetlink_alloc_expect(cda, ct, &tuple, &mask);
+ exp = ctnetlink_alloc_expect(cda, ct, NULL, &tuple, &mask);
if (IS_ERR(exp)) {
err = PTR_ERR(exp);
goto err_rcu;
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index bd91b8b47f4b..4f975b83c84f 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -1386,7 +1386,7 @@ static int process_register_request(struct sk_buff *skb, unsigned int protoff,
nf_ct_expect_init(exp, SIP_EXPECT_SIGNALLING, nf_ct_l3num(ct),
saddr, &daddr, proto, NULL, &port);
exp->timeout.expires = sip_timeout * HZ;
- rcu_assign_pointer(exp->helper, helper);
+ rcu_assign_pointer(exp->assign_helper, helper);
exp->flags = NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE;
hooks = rcu_dereference(nf_nat_sip_hooks);
@@ -1629,7 +1629,7 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff,
unsigned int matchoff, matchlen;
unsigned int msglen, origlen;
const char *dptr, *end;
- s16 diff, tdiff = 0;
+ s32 diff, tdiff = 0;
int ret = NF_ACCEPT;
unsigned long clen;
bool term;
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 1d5de1d9f008..a0434ac356ee 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -1113,7 +1113,7 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net)
static void nf_conntrack_standalone_fini_sysctl(struct net *net)
{
struct nf_conntrack_net *cnet = nf_ct_pernet(net);
- struct ctl_table *table;
+ const struct ctl_table *table;
table = cnet->sysctl_header->ctl_table_arg;
unregister_net_sysctl_table(cnet->sysctl_header);
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index 75c812f157e2..3cc569ac8a06 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -509,7 +509,7 @@ static int netfilter_log_sysctl_init(struct net *net)
static void netfilter_log_sysctl_exit(struct net *net)
{
- struct ctl_table *table;
+ const struct ctl_table *table;
table = net->nf.nf_log_dir_header->ctl_table_arg;
unregister_net_sysctl_table(net->nf.nf_log_dir_header);
diff --git a/net/netfilter/nf_nat_sip.c b/net/netfilter/nf_nat_sip.c
index f7be30c69b5c..a1c41defaf22 100644
--- a/net/netfilter/nf_nat_sip.c
+++ b/net/netfilter/nf_nat_sip.c
@@ -315,7 +315,7 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff,
}
static void nf_nat_sip_seq_adjust(struct sk_buff *skb, unsigned int protoff,
- s16 off)
+ s32 off)
{
enum ip_conntrack_info ctinfo;
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index fb469623f9cf..2c894a7d8a40 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -655,6 +655,11 @@ static void nft_map_catchall_deactivate(const struct nft_ctx *ctx,
}
}
+/* Use NFT_ITER_UPDATE iterator even if this may be called from the preparation
+ * phase, the set clone might already exist from a previous command, or it might
+ * be a set that is going away and does not require a clone. The netns and
+ * netlink release paths also need to work on the live set.
+ */
static void nft_map_deactivate(const struct nft_ctx *ctx, struct nft_set *set)
{
struct nft_set_iter iter = {
@@ -7396,9 +7401,12 @@ static int nft_set_catchall_flush(const struct nft_ctx *ctx,
static int nft_set_flush(struct nft_ctx *ctx, struct nft_set *set, u8 genmask)
{
+ /* The set backend might need to clone the set, do it now from the
+ * preparation phase, use NFT_ITER_UPDATE_CLONE iterator type.
+ */
struct nft_set_iter iter = {
.genmask = genmask,
- .type = NFT_ITER_UPDATE,
+ .type = NFT_ITER_UPDATE_CLONE,
.fn = nft_setelem_flush,
};
diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c
index 36c31ad2d64c..15feb49e0b66 100644
--- a/net/netfilter/nft_payload.c
+++ b/net/netfilter/nft_payload.c
@@ -253,9 +253,7 @@ static int nft_payload_dump(struct sk_buff *skb,
static bool nft_payload_offload_mask(struct nft_offload_reg *reg,
u32 priv_len, u32 field_len)
{
- unsigned int remainder, delta, k;
struct nft_data mask = {};
- __be32 remainder_mask;
if (priv_len == field_len) {
memset(®->mask, 0xff, priv_len);
@@ -264,15 +262,7 @@ static bool nft_payload_offload_mask(struct nft_offload_reg *reg,
return false;
}
- memset(&mask, 0xff, field_len);
- remainder = priv_len % sizeof(u32);
- if (remainder) {
- k = priv_len / sizeof(u32);
- delta = field_len - priv_len;
- remainder_mask = htonl(~((1 << (delta * BITS_PER_BYTE)) - 1));
- mask.data[k] = (__force u32)remainder_mask;
- }
-
+ memset(&mask, 0xff, priv_len);
memcpy(®->mask, &mask, field_len);
return true;
diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c
index 4a6561ba6061..7c8d28a031ad 100644
--- a/net/netfilter/nft_set_pipapo.c
+++ b/net/netfilter/nft_set_pipapo.c
@@ -2199,13 +2199,20 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
const struct nft_pipapo_match *m;
switch (iter->type) {
- case NFT_ITER_UPDATE:
+ case NFT_ITER_UPDATE_CLONE:
m = pipapo_maybe_clone(set);
if (!m) {
iter->err = -ENOMEM;
return;
}
-
+ nft_pipapo_do_walk(ctx, set, m, iter);
+ break;
+ case NFT_ITER_UPDATE:
+ if (priv->clone)
+ m = priv->clone;
+ else
+ m = rcu_dereference_protected(priv->match,
+ nft_pipapo_transaction_mutex_held(set));
nft_pipapo_do_walk(ctx, set, m, iter);
break;
case NFT_ITER_READ:
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index 0859b8f76764..61813010cd31 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -118,6 +118,7 @@ struct xt_hashlimit_htable {
refcount_t use;
u_int8_t family;
bool rnd_initialized;
+ bool ratematch;
struct hashlimit_cfg3 cfg; /* config */
@@ -325,6 +326,7 @@ static int htable_create(struct net *net, struct hashlimit_cfg3 *cfg,
vfree(hinfo);
return -ENOMEM;
}
+ hinfo->ratematch = !!(cfg->mode & XT_HASHLIMIT_RATE_MATCH);
spin_lock_init(&hinfo->lock);
switch (revision) {
@@ -868,7 +870,10 @@ static int hashlimit_mt_check_common(const struct xt_mtchk_param *par,
}
/* Check for overflow. */
- if (revision >= 3 && cfg->mode & XT_HASHLIMIT_RATE_MATCH) {
+ if (cfg->mode & XT_HASHLIMIT_RATE_MATCH) {
+ if (revision < 3)
+ return -EINVAL;
+
if (cfg->avg == 0 || cfg->avg > U32_MAX) {
pr_info_ratelimited("invalid rate\n");
return -ERANGE;
@@ -901,6 +906,15 @@ static int hashlimit_mt_check_common(const struct xt_mtchk_param *par,
mutex_unlock(&hashlimit_mutex);
return ret;
}
+ } else {
+ if ((cfg->mode & XT_HASHLIMIT_RATE_MATCH &&
+ !(*hinfo)->ratematch) ||
+ (!(cfg->mode & XT_HASHLIMIT_RATE_MATCH) &&
+ (*hinfo)->ratematch)) {
+ mutex_unlock(&hashlimit_mutex);
+ htable_put(*hinfo);
+ return -EINVAL;
+ }
}
mutex_unlock(&hashlimit_mutex);
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 793f86e24755..4cdf0f09d488 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -1120,6 +1120,10 @@ static int execute_masked_set_action(struct sk_buff *skb,
return err;
}
+/* When 'last' is true, recirc() should always consume the 'skb'.
+ * Otherwise, recirc() should keep 'skb' intact regardless what
+ * actions are executed on recirculation.
+ */
static int execute_recirc(struct datapath *dp, struct sk_buff *skb,
struct sw_flow_key *key,
const struct nlattr *a, bool last)
@@ -1130,8 +1134,12 @@ static int execute_recirc(struct datapath *dp, struct sk_buff *skb,
int err;
err = ovs_flow_key_update(skb, key);
- if (err)
+ if (err) {
+ if (last)
+ ovs_kfree_skb_reason(skb,
+ OVS_DROP_ACTION_ERROR);
return err;
+ }
}
BUG_ON(!is_flow_key_valid(key));
@@ -1346,7 +1354,7 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
if (!is_flow_key_valid(key)) {
err = ovs_flow_key_update(skb, key);
if (err)
- return err;
+ break;
}
err = ovs_ct_execute(ovs_dp_get_net(dp), skb, key,
diff --git a/net/openvswitch/meter.c b/net/openvswitch/meter.c
index cc08e0403909..671984edfe1e 100644
--- a/net/openvswitch/meter.c
+++ b/net/openvswitch/meter.c
@@ -133,18 +133,10 @@ static void dp_meter_instance_remove(struct dp_meter_instance *ti,
static int attach_meter(struct dp_meter_table *tbl, struct dp_meter *meter)
{
- struct dp_meter_instance *ti = rcu_dereference_ovsl(tbl->ti);
- u32 hash = meter_hash(ti, meter->id);
+ struct dp_meter_instance *ti;
+ u32 hash;
int err;
- /* In generally, slots selected should be empty, because
- * OvS uses id-pool to fetch a available id.
- */
- if (unlikely(rcu_dereference_ovsl(ti->dp_meters[hash])))
- return -EBUSY;
-
- dp_meter_instance_insert(ti, meter);
-
/* That function is thread-safe. */
tbl->count++;
if (tbl->count >= tbl->max_meters_allowed) {
@@ -152,16 +144,29 @@ static int attach_meter(struct dp_meter_table *tbl, struct dp_meter *meter)
goto attach_err;
}
- if (tbl->count >= ti->n_meters &&
- dp_meter_instance_realloc(tbl, ti->n_meters * 2)) {
- err = -ENOMEM;
+ ti = rcu_dereference_ovsl(tbl->ti);
+ if (tbl->count >= ti->n_meters) {
+ err = dp_meter_instance_realloc(tbl, ti->n_meters * 2);
+ if (err)
+ goto attach_err;
+
+ ti = rcu_dereference_ovsl(tbl->ti);
+ }
+
+ hash = meter_hash(ti, meter->id);
+
+ /* In general, selected slots should be empty, because
+ * OvS uses id-pool to fetch available ids.
+ */
+ if (unlikely(rcu_dereference_ovsl(ti->dp_meters[hash]))) {
+ err = -EBUSY;
goto attach_err;
}
+ dp_meter_instance_insert(ti, meter);
return 0;
attach_err:
- dp_meter_instance_remove(ti, meter);
tbl->count--;
return err;
}
diff --git a/net/rds/ib.c b/net/rds/ib.c
index ce5be43c5fba..1061bcf7d131 100644
--- a/net/rds/ib.c
+++ b/net/rds/ib.c
@@ -431,6 +431,10 @@ static int rds_ib_laddr_check_cm(struct net *net, const struct in6_addr *addr,
sa = (struct sockaddr *)&sin;
} else {
#if IS_ENABLED(CONFIG_IPV6)
+ if (!ipv6_mod_enabled()) {
+ ret = -EADDRNOTAVAIL;
+ goto out;
+ }
memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
sin6.sin6_addr = *addr;
diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c
index 5289afbb61aa..e50e01abb079 100644
--- a/net/rds/ib_cm.c
+++ b/net/rds/ib_cm.c
@@ -810,6 +810,10 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
dp = event->param.conn.private_data;
if (isv6) {
#if IS_ENABLED(CONFIG_IPV6)
+ if (!ipv6_mod_enabled()) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
dp_cmn = &dp->ricp_v6.dp_cmn;
saddr6 = &dp->ricp_v6.dp_saddr;
daddr6 = &dp->ricp_v6.dp_daddr;
diff --git a/net/rds/tcp.c b/net/rds/tcp.c
index dee18da64a32..997aee359025 100644
--- a/net/rds/tcp.c
+++ b/net/rds/tcp.c
@@ -330,21 +330,25 @@ int rds_tcp_laddr_check(struct net *net, const struct in6_addr *addr,
/* If the scope_id is specified, check only those addresses
* hosted on the specified interface.
*/
+ rcu_read_lock();
if (scope_id != 0) {
- rcu_read_lock();
dev = dev_get_by_index_rcu(net, scope_id);
/* scope_id is not valid... */
if (!dev) {
rcu_read_unlock();
return -EADDRNOTAVAIL;
}
- rcu_read_unlock();
}
#if IS_ENABLED(CONFIG_IPV6)
- ret = ipv6_chk_addr(net, addr, dev, 0);
- if (ret)
- return 0;
+ if (ipv6_mod_enabled()) {
+ ret = ipv6_chk_addr(net, addr, dev, 0);
+ if (ret) {
+ rcu_read_unlock();
+ return 0;
+ }
+ }
#endif
+ rcu_read_unlock();
return -EADDRNOTAVAIL;
}
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 5f5421680b2e..494a87be3d85 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -1188,6 +1188,7 @@ struct rxrpc_peer *rxrpc_lookup_peer_rcu(struct rxrpc_local *,
const struct sockaddr_rxrpc *);
struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_local *local,
struct sockaddr_rxrpc *srx, gfp_t gfp);
+void rxrpc_assess_MTU_size(struct rxrpc_local *local, struct rxrpc_peer *peer);
struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *, gfp_t,
enum rxrpc_peer_trace);
void rxrpc_new_incoming_peer(struct rxrpc_local *local, struct rxrpc_peer *peer);
diff --git a/net/rxrpc/call_accept.c b/net/rxrpc/call_accept.c
index cbf6187d68ed..66994e3698ef 100644
--- a/net/rxrpc/call_accept.c
+++ b/net/rxrpc/call_accept.c
@@ -407,6 +407,7 @@ bool rxrpc_new_incoming_call(struct rxrpc_local *local,
spin_unlock(&rx->incoming_lock);
read_unlock_irq(&local->services_lock);
+ rxrpc_assess_MTU_size(local, call->peer);
if (hlist_unhashed(&call->error_link)) {
spin_lock_irq(&call->peer->lock);
diff --git a/net/rxrpc/peer_object.c b/net/rxrpc/peer_object.c
index 3a4cf95ecddf..782608141029 100644
--- a/net/rxrpc/peer_object.c
+++ b/net/rxrpc/peer_object.c
@@ -147,8 +147,7 @@ struct rxrpc_peer *rxrpc_lookup_peer_rcu(struct rxrpc_local *local,
* assess the MTU size for the network interface through which this peer is
* reached
*/
-static void rxrpc_assess_MTU_size(struct rxrpc_local *local,
- struct rxrpc_peer *peer)
+void rxrpc_assess_MTU_size(struct rxrpc_local *local, struct rxrpc_peer *peer)
{
struct net *net = local->net;
struct dst_entry *dst;
@@ -160,6 +159,8 @@ static void rxrpc_assess_MTU_size(struct rxrpc_local *local,
#endif
peer->if_mtu = 1500;
+ peer->mtu = peer->if_mtu;
+ peer->maxdata = peer->mtu - peer->hdrsize;
memset(&fl, 0, sizeof(fl));
switch (peer->srx.transport.family) {
@@ -199,6 +200,9 @@ static void rxrpc_assess_MTU_size(struct rxrpc_local *local,
peer->if_mtu = dst_mtu(dst);
dst_release(dst);
+ peer->mtu = peer->if_mtu;
+ peer->maxdata = peer->mtu - peer->hdrsize;
+
_leave(" [if_mtu %u]", peer->if_mtu);
}
@@ -240,8 +244,6 @@ static void rxrpc_init_peer(struct rxrpc_local *local, struct rxrpc_peer *peer,
unsigned long hash_key)
{
peer->hash_key = hash_key;
- rxrpc_assess_MTU_size(local, peer);
- peer->mtu = peer->if_mtu;
peer->rtt_last_req = ktime_get_real();
switch (peer->srx.transport.family) {
@@ -266,7 +268,6 @@ static void rxrpc_init_peer(struct rxrpc_local *local, struct rxrpc_peer *peer,
}
peer->hdrsize += sizeof(struct rxrpc_wire_header);
- peer->maxdata = peer->mtu - peer->hdrsize;
}
/*
@@ -285,6 +286,7 @@ static struct rxrpc_peer *rxrpc_create_peer(struct rxrpc_local *local,
if (peer) {
memcpy(&peer->srx, srx, sizeof(*srx));
rxrpc_init_peer(local, peer, hash_key);
+ rxrpc_assess_MTU_size(local, peer);
}
_leave(" = %p", peer);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 0b0794f164cf..44f06c5f1f25 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -614,6 +614,9 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
return peer;
}
+ if (asoc->peer.transport_count == U16_MAX)
+ return NULL;
+
peer = sctp_transport_new(asoc->base.net, addr, gfp);
if (!peer)
return NULL;
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 2185f44198de..e4b457570846 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -1394,10 +1394,6 @@ static int __net_init sctp_defaults_init(struct net *net)
net->sctp.l3mdev_accept = 1;
#endif
- status = sctp_sysctl_net_register(net);
- if (status)
- goto err_sysctl_register;
-
/* Allocate and initialise sctp mibs. */
status = init_sctp_mibs(net);
if (status)
@@ -1431,8 +1427,6 @@ static int __net_init sctp_defaults_init(struct net *net)
cleanup_sctp_mibs(net);
#endif
err_init_mibs:
- sctp_sysctl_net_unregister(net);
-err_sysctl_register:
return status;
}
@@ -1447,7 +1441,6 @@ static void __net_exit sctp_defaults_exit(struct net *net)
net->sctp.proc_net_sctp = NULL;
#endif
cleanup_sctp_mibs(net);
- sctp_sysctl_net_unregister(net);
}
static struct pernet_operations sctp_defaults_ops = {
@@ -1461,16 +1454,28 @@ static int __net_init sctp_ctrlsock_init(struct net *net)
/* Initialize the control inode/socket for handling OOTB packets. */
status = sctp_ctl_sock_init(net);
- if (status)
+ if (status) {
pr_err("Failed to initialize the SCTP control sock\n");
+ return status;
+ }
+
+ status = sctp_sysctl_net_register(net);
+ if (status) {
+ inet_ctl_sock_destroy(net->sctp.ctl_sock);
+ net->sctp.ctl_sock = NULL;
+ }
return status;
}
static void __net_exit sctp_ctrlsock_exit(struct net *net)
{
+ sctp_sysctl_net_unregister(net);
+ sctp_udp_sock_stop(net);
+
/* Free the control endpoint. */
inet_ctl_sock_destroy(net->sctp.ctl_sock);
+ net->sctp.ctl_sock = NULL;
}
static struct pernet_operations sctp_ctrlsock_ops = {
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 9ed8f502a9c1..0f03560fcab4 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1821,9 +1821,9 @@ struct sctp_association *sctp_unpack_cookie(
goto fail;
}
- /* Check to see if the cookie is stale. If there is already
- * an association, there is no need to check cookie's expiration
- * for init collision case of lost COOKIE ACK.
+ /* Check to see if the cookie is stale. RFC 9260 Section 5.2.4
+ * exempts an expired cookie only when both Verification Tags match
+ * the current association.
* If skb has been timestamped, then use the stamp, otherwise
* use current time. This introduces a small possibility that
* a cookie may be considered expired, but this would only slow
@@ -1834,7 +1834,10 @@ struct sctp_association *sctp_unpack_cookie(
else
kt = ktime_get_real();
- if (!asoc && ktime_before(bear_cookie->expiration, kt)) {
+ if ((!asoc ||
+ asoc->c.my_vtag != bear_cookie->my_vtag ||
+ asoc->c.peer_vtag != bear_cookie->peer_vtag) &&
+ ktime_before(bear_cookie->expiration, kt)) {
suseconds_t usecs = ktime_to_us(ktime_sub(kt, bear_cookie->expiration));
__be32 n = htonl(usecs);
@@ -2187,7 +2190,13 @@ static enum sctp_ierror sctp_verify_param(struct net *net,
case SCTP_PARAM_HEARTBEAT_INFO:
case SCTP_PARAM_UNRECOGNIZED_PARAMETERS:
case SCTP_PARAM_ECN_CAPABLE:
+ break;
case SCTP_PARAM_ADAPTATION_LAYER_IND:
+ if (ntohs(param.p->length) != sizeof(*param.aind)) {
+ sctp_process_inv_paramlength(asoc, param.p,
+ chunk, err_chunk);
+ retval = SCTP_IERROR_ABORT;
+ }
break;
case SCTP_PARAM_SUPPORTED_EXT:
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 77a76634014a..ac9cbc4bf8c5 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -630,11 +630,16 @@ int sctp_sysctl_net_register(struct net *net)
void sctp_sysctl_net_unregister(struct net *net)
{
- struct ctl_table *table;
+ struct ctl_table_header *header = net->sctp.sysctl_header;
+ const struct ctl_table *table;
+
+ if (!header)
+ return;
- table = net->sctp.sysctl_header->ctl_table_arg;
- unregister_net_sysctl_table(net->sctp.sysctl_header);
+ table = header->ctl_table_arg;
+ unregister_net_sysctl_table(header);
kfree(table);
+ net->sctp.sysctl_header = NULL;
}
static struct ctl_table_header *sctp_sysctl_header;
diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c
index 3c626c014d1d..1e27617a5f88 100644
--- a/net/smc/smc_core.c
+++ b/net/smc/smc_core.c
@@ -1502,10 +1502,10 @@ static void __smc_lgr_terminate(struct smc_link_group *lgr, bool soft)
read_lock_bh(&lgr->conns_lock);
node = rb_first(&lgr->conns_all);
while (node) {
- read_unlock_bh(&lgr->conns_lock);
conn = rb_entry(node, struct smc_connection, alert_node);
smc = container_of(conn, struct smc_sock, conn);
sock_hold(&smc->sk); /* sock_put below */
+ read_unlock_bh(&lgr->conns_lock);
lock_sock(&smc->sk);
smc_conn_kill(conn, soft);
release_sock(&smc->sk);
diff --git a/net/smc/smc_sysctl.c b/net/smc/smc_sysctl.c
index 5cbc18c6e62b..c632df62ff90 100644
--- a/net/smc/smc_sysctl.c
+++ b/net/smc/smc_sysctl.c
@@ -109,7 +109,7 @@ int __net_init smc_sysctl_net_init(struct net *net)
void __net_exit smc_sysctl_net_exit(struct net *net)
{
- struct ctl_table *table;
+ const struct ctl_table *table;
table = net->smc.smc_hdr->ctl_table_arg;
unregister_net_sysctl_table(net->smc.smc_hdr);
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 4fefe9cf721f..6d9bc9397b03 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -798,7 +798,7 @@ static __poll_t tipc_poll(struct file *file, struct socket *sock,
__poll_t revents = 0;
sock_poll_wait(file, sock, wait);
- trace_tipc_sk_poll(sk, NULL, TIPC_DUMP_ALL, " ");
+ trace_tipc_sk_poll(sk, NULL, TIPC_DUMP_NONE, " ");
if (sk->sk_shutdown & RCV_SHUTDOWN)
revents |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM;
diff --git a/net/unix/sysctl_net_unix.c b/net/unix/sysctl_net_unix.c
index 3e84b31c355a..44996af61999 100644
--- a/net/unix/sysctl_net_unix.c
+++ b/net/unix/sysctl_net_unix.c
@@ -52,7 +52,7 @@ int __net_init unix_sysctl_register(struct net *net)
void unix_sysctl_unregister(struct net *net)
{
- struct ctl_table *table;
+ const struct ctl_table *table;
table = net->unx.ctl->ctl_table_arg;
unregister_net_sysctl_table(net->unx.ctl);
diff --git a/net/xfrm/xfrm_sysctl.c b/net/xfrm/xfrm_sysctl.c
index 7fdeafc838a7..e972930c292b 100644
--- a/net/xfrm/xfrm_sysctl.c
+++ b/net/xfrm/xfrm_sysctl.c
@@ -76,7 +76,7 @@ int __net_init xfrm_sysctl_init(struct net *net)
void __net_exit xfrm_sysctl_fini(struct net *net)
{
- struct ctl_table *table;
+ const struct ctl_table *table;
table = net->xfrm.sysctl_hdr->ctl_table_arg;
unregister_net_sysctl_table(net->xfrm.sysctl_hdr);
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index e105349794f2..fd95a0eb7a46 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -271,6 +271,7 @@ static unsigned long keyring_get_key_chunk(const void *data, int level)
unsigned long chunk = 0;
const u8 *d;
int desc_len = index_key->desc_len, n = sizeof(chunk);
+ unsigned int offset;
level /= ASSOC_ARRAY_KEY_CHUNK_SIZE;
switch (level) {
@@ -284,17 +285,18 @@ static unsigned long keyring_get_key_chunk(const void *data, int level)
return (unsigned long)index_key->domain_tag;
default:
level -= 4;
- if (desc_len <= sizeof(index_key->desc))
+ offset = sizeof(index_key->desc) + level * sizeof(long);
+ if (desc_len <= offset)
return 0;
- d = index_key->description + sizeof(index_key->desc);
- d += level * sizeof(long);
- desc_len -= sizeof(index_key->desc);
+ d = index_key->description + offset;
+ desc_len -= offset;
if (desc_len > n)
desc_len = n;
+ d += desc_len;
do {
chunk <<= 8;
- chunk |= *d++;
+ chunk |= *--d;
} while (--desc_len > 0);
return chunk;
}
@@ -375,7 +377,7 @@ static int keyring_diff_objects(const void *object, const void *data)
return -1;
differ_plus_i:
- level += i;
+ level += i - (int)sizeof(a->desc);
differ:
i = level * 8 + __ffs(seg_a ^ seg_b);
return i;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index c1b7ee1f3e74..35616d0d528d 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -2354,6 +2354,7 @@ static void relink_to_local(struct snd_pcm_substream *substream)
static int snd_pcm_unlink(struct snd_pcm_substream *substream)
{
+ struct snd_pcm_substream *s;
struct snd_pcm_group *group;
bool nonatomic = substream->pcm->nonatomic;
bool do_free = false;
@@ -2369,6 +2370,12 @@ static int snd_pcm_unlink(struct snd_pcm_substream *substream)
group = substream->group;
snd_pcm_group_lock_irq(group, nonatomic);
+ /* release drain waiters before changing membership, else snd_pcm_drain()
+ * leaves its on-stack wait entry queued on a member's sleep list
+ */
+ snd_pcm_group_for_each_entry(s, substream)
+ wake_up(&s->runtime->sleep);
+
relink_to_local(substream);
refcount_dec(&group->refs);
diff --git a/sound/core/ump.c b/sound/core/ump.c
index 32d27e58416a..650cbe7b3a97 100644
--- a/sound/core/ump.c
+++ b/sound/core/ump.c
@@ -1286,6 +1286,7 @@ int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump,
&rmidi);
if (err < 0) {
kfree(ump->out_cvts);
+ ump->out_cvts = NULL;
return err;
}
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 763c92a848d4..c2b00b6768ac 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -111,6 +111,15 @@ struct hdmi_ops {
hda_nid_t pin_nid, int dev_id, u32 stream_tag,
int format);
+ /*
+ * Optional hook invoked at the beginning of the PCM prepare
+ * sequence, before the audio infoframe and stream format are
+ * (re)programmed. Used to disable keep-alive / silent stream so
+ * that the format change is not done while keep-alive is active.
+ */
+ void (*prepare)(struct hda_codec *codec,
+ struct hdmi_spec_per_pin *per_pin);
+
void (*pin_cvt_fixup)(struct hda_codec *codec,
struct hdmi_spec_per_pin *per_pin,
hda_nid_t cvt_nid);
@@ -2134,6 +2143,9 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
per_pin->channels = substream->runtime->channels;
per_pin->setup = true;
+ if (spec->ops.prepare)
+ spec->ops.prepare(codec, per_pin);
+
if (get_wcaps(codec, cvt_nid) & AC_WCAP_STRIPE) {
stripe = snd_hdac_get_stream_stripe_ctl(&codec->bus->core,
substream);
@@ -2905,6 +2917,28 @@ static void register_i915_notifier(struct hda_codec *codec)
codec->relaxed_resume = 1;
}
+/*
+ * prepare ops override for HSW+
+ *
+ * Disable keep-alive before the converter format and audio infoframe are
+ * reprogrammed by the PCM prepare sequence. Changing the audio format (e.g.
+ * the channel count when switching to multichannel PCM) while a keep-alive
+ * stream is active is not safe, so release keep-alive here, early in the
+ * sequence. It is re-enabled once the new stream has been set up, in
+ * i915_hsw_setup_stream().
+ */
+static void i915_hsw_prepare(struct hda_codec *codec,
+ struct hdmi_spec_per_pin *per_pin)
+{
+ struct hdmi_spec *spec = codec->spec;
+
+ if (spec->silent_stream_type == SILENT_STREAM_KAE && per_pin->silent_stream) {
+ silent_stream_set_kae(codec, per_pin, false);
+ /* wait for pending transfers in codec to clear */
+ usleep_range(100, 200);
+ }
+}
+
/* setup_stream ops override for HSW+ */
static int i915_hsw_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
hda_nid_t pin_nid, int dev_id, u32 stream_tag,
@@ -2922,15 +2956,16 @@ static int i915_hsw_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
haswell_verify_D0(codec, cvt_nid, pin_nid);
- if (spec->silent_stream_type == SILENT_STREAM_KAE && per_pin && per_pin->silent_stream) {
- silent_stream_set_kae(codec, per_pin, false);
- /* wait for pending transfers in codec to clear */
- usleep_range(100, 200);
- }
-
res = hdmi_setup_stream(codec, cvt_nid, pin_nid, dev_id,
stream_tag, format);
+ /*
+ * Keep-alive was disabled in i915_hsw_prepare(), re-enable it now.
+ * The pin lookup above resolves to the same per_pin that prepare
+ * used (pin_nid comes from that per_pin), so this stays balanced; a
+ * NULL per_pin only occurs on a lookup failure that also implies no
+ * active keep-alive stream to restore.
+ */
if (spec->silent_stream_type == SILENT_STREAM_KAE && per_pin && per_pin->silent_stream) {
usleep_range(100, 200);
silent_stream_set_kae(codec, per_pin, true);
@@ -3106,6 +3141,7 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid,
codec->depop_delay = 0;
codec->auto_runtime_pm = 1;
+ spec->ops.prepare = i915_hsw_prepare;
spec->ops.setup_stream = i915_hsw_setup_stream;
spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup;
diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c
index bd9b6148dd6f..45ef869ae9e5 100644
--- a/sound/pci/lx6464es/lx6464es.c
+++ b/sound/pci/lx6464es/lx6464es.c
@@ -410,11 +410,8 @@ static void lx_trigger_start(struct lx6464es *chip, struct lx_stream *lx_stream)
int err;
- const u32 channels = substream->runtime->channels;
- const u32 bytes_per_frame = channels * 3;
- const u32 period_size = substream->runtime->period_size;
const u32 periods = substream->runtime->periods;
- const u32 period_bytes = period_size * bytes_per_frame;
+ const u32 period_bytes = snd_pcm_lib_period_bytes(substream);
dma_addr_t buf = substream->dma_buffer.addr;
int i;
diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c
index c3f2717aebf2..129199e3ac06 100644
--- a/sound/pci/lx6464es/lx_core.c
+++ b/sound/pci/lx6464es/lx_core.c
@@ -1015,10 +1015,7 @@ static int lx_interrupt_request_new_buffer(struct lx6464es *chip,
const unsigned int is_capture = lx_stream->is_capture;
int err;
- const u32 channels = substream->runtime->channels;
- const u32 bytes_per_frame = channels * 3;
- const u32 period_size = substream->runtime->period_size;
- const u32 period_bytes = period_size * bytes_per_frame;
+ const u32 period_bytes = snd_pcm_lib_period_bytes(substream);
const u32 pos = lx_stream->frame_pos;
const u32 next_pos = ((pos+1) == substream->runtime->periods) ?
0 : pos + 1;
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
index 4023b88e7bc1..9253707bccde 100644
--- a/sound/soc/codecs/max98090.c
+++ b/sound/soc/codecs/max98090.c
@@ -2388,8 +2388,9 @@ static int max98090_probe(struct snd_soc_component *component)
dev_dbg(component->dev, "max98090_probe\n");
max98090->mclk = devm_clk_get(component->dev, "mclk");
- if (PTR_ERR(max98090->mclk) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
+ if (IS_ERR(max98090->mclk))
+ if (PTR_ERR(max98090->mclk) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
max98090->component = component;
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index 7e525d49328d..3b37f4c4235e 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -1984,8 +1984,9 @@ static int max98095_probe(struct snd_soc_component *component)
int ret = 0;
max98095->mclk = devm_clk_get(component->dev, "mclk");
- if (PTR_ERR(max98095->mclk) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
+ if (IS_ERR(max98095->mclk))
+ if (PTR_ERR(max98095->mclk) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
/* reset the codec, the DSP core, and disable all interrupts */
max98095_reset(component);
diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c
index a109315a8c05..a1cb2d723ea5 100644
--- a/sound/soc/codecs/tas2562.c
+++ b/sound/soc/codecs/tas2562.c
@@ -32,15 +32,16 @@
static const unsigned int float_vol_db_lookup[] = {
0x00000d43, 0x000010b2, 0x00001505, 0x00001a67, 0x00002151,
0x000029f1, 0x000034cd, 0x00004279, 0x000053af, 0x0000695b,
-0x0000695b, 0x0000a6fa, 0x0000d236, 0x000108a4, 0x00014d2a,
+0x000084a3, 0x0000a6fa, 0x0000d236, 0x000108a4, 0x00014d2a,
0x0001a36e, 0x00021008, 0x000298c0, 0x000344df, 0x00041d8f,
0x00052e5a, 0x000685c8, 0x00083621, 0x000a566d, 0x000d03a7,
0x0010624d, 0x0014a050, 0x0019f786, 0x0020b0bc, 0x0029279d,
0x0033cf8d, 0x004139d3, 0x00521d50, 0x00676044, 0x0082248a,
0x00a3d70a, 0x00ce4328, 0x0103ab3d, 0x0146e75d, 0x019b8c27,
0x02061b89, 0x028c423f, 0x03352529, 0x0409c2b0, 0x05156d68,
-0x080e9f96, 0x0a24b062, 0x0cc509ab, 0x10137987, 0x143d1362,
-0x197a967f, 0x2013739e, 0x28619ae9, 0x32d64617, 0x40000000
+0x06666666, 0x080e9f96, 0x0a24b062, 0x0cc509ab, 0x10137987,
+0x143d1362, 0x197a967f, 0x2013739e, 0x28619ae9, 0x32d64617,
+0x40000000
};
struct tas2562_data {
@@ -476,20 +477,27 @@ static int tas2562_volume_control_put(struct snd_kcontrol *kcontrol,
u32 reg_val;
reg_val = float_vol_db_lookup[ucontrol->value.integer.value[0]/2];
- ret = snd_soc_component_write(component, TAS2562_DVC_CFG4,
- (reg_val & 0xff));
- if (ret)
- return ret;
- ret = snd_soc_component_write(component, TAS2562_DVC_CFG3,
- ((reg_val >> 8) & 0xff));
+ /*
+ * The device applies the 32-bit coefficient to the playback path on
+ * the write to DVC_CFG4 (the LSB, book 0 page 2 reg 0x0F), so the
+ * bytes must be written MSB first and DVC_CFG4 last. Writing CFG4
+ * first latches a mix of the previous coefficient's upper bytes and
+ * the new LSB instead of the requested value.
+ */
+ ret = snd_soc_component_write(component, TAS2562_DVC_CFG1,
+ ((reg_val >> 24) & 0xff));
if (ret)
return ret;
ret = snd_soc_component_write(component, TAS2562_DVC_CFG2,
((reg_val >> 16) & 0xff));
if (ret)
return ret;
- ret = snd_soc_component_write(component, TAS2562_DVC_CFG1,
- ((reg_val >> 24) & 0xff));
+ ret = snd_soc_component_write(component, TAS2562_DVC_CFG3,
+ ((reg_val >> 8) & 0xff));
+ if (ret)
+ return ret;
+ ret = snd_soc_component_write(component, TAS2562_DVC_CFG4,
+ (reg_val & 0xff));
if (ret)
return ret;
diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c
index 835295e0807d..e5916c6b75ae 100644
--- a/sound/usb/6fire/chip.c
+++ b/sound/usb/6fire/chip.c
@@ -158,6 +158,10 @@ static int usb6fire_chip_probe(struct usb_interface *intf,
return 0;
destroy_chip:
+ chip->shutdown = true;
+ if (card)
+ snd_card_disconnect(card);
+ usb6fire_chip_abort(chip);
snd_card_free(card);
return ret;
}
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index b399a7065cf3..59e3584b24a0 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -1185,10 +1185,12 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep)
<< (16 - ep->datainterval);
}
- if (ep->fill_max)
+ if (ep->fill_max) {
ep->curpacksize = ep->maxpacksize;
- else
+ maxsize = ep->curpacksize;
+ } else {
ep->curpacksize = maxsize;
+ }
if (snd_usb_get_speed(chip->dev) != USB_SPEED_FULL) {
packs_per_ms = 8 >> ep->datainterval;
@@ -1832,11 +1834,13 @@ static void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
out_packet->packets = in_ctx->packets;
for (i = 0; i < in_ctx->packets; i++) {
- if (urb->iso_frame_desc[i].status == 0)
- out_packet->packet_size[i] =
+ if (urb->iso_frame_desc[i].status == 0) {
+ unsigned int frames =
urb->iso_frame_desc[i].actual_length / sender->stride;
- else
+ out_packet->packet_size[i] = min(frames, ep->maxframesize);
+ } else {
out_packet->packet_size[i] = 0;
+ }
}
spin_unlock_irqrestore(&ep->lock, flags);
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index c2f63d0c6c33..30a119f9f779 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -800,6 +800,8 @@ static void snd_usbmidi_akai_output(struct snd_usb_midi_out_endpoint *ep,
msg = urb->transfer_buffer + urb->transfer_buffer_length;
buf_end = ep->max_transfer - MAX_AKAI_SYSEX_LEN - 1;
+ if (buf_end <= 0)
+ return;
/* only try adding more data when there's space for at least 1 SysEx */
while (urb->transfer_buffer_length < buf_end) {
diff --git a/sound/usb/midi2.c b/sound/usb/midi2.c
index 925399e2cbbc..f70e5ec66edb 100644
--- a/sound/usb/midi2.c
+++ b/sound/usb/midi2.c
@@ -337,7 +337,7 @@ ump_to_endpoint(struct snd_ump_endpoint *ump, int dir)
{
struct snd_usb_midi2_ump *rmidi = ump->private_data;
- return rmidi->eps[dir];
+ return rmidi ? rmidi->eps[dir] : NULL;
}
/* ump open callback */
@@ -703,6 +703,8 @@ static void free_all_midi2_umps(struct snd_usb_midi2_interface *umidi)
rmidi = list_first_entry(&umidi->rawmidi_list,
struct snd_usb_midi2_ump, list);
list_del(&rmidi->list);
+ if (rmidi->ump)
+ rmidi->ump->private_data = NULL;
kfree(rmidi);
}
}
diff --git a/tools/testing/selftests/clone3/clone3_set_tid.c b/tools/testing/selftests/clone3/clone3_set_tid.c
index 0229e9ebb995..a0cc8940e8f8 100644
--- a/tools/testing/selftests/clone3/clone3_set_tid.c
+++ b/tools/testing/selftests/clone3/clone3_set_tid.c
@@ -146,7 +146,7 @@ int main(int argc, char *argv[])
{
FILE *f;
char buf;
- char *line;
+ char *line = NULL;
int status;
int ret = -1;
size_t len = 0;
diff --git a/tools/testing/selftests/mm/mlock-random-test.c b/tools/testing/selftests/mm/mlock-random-test.c
index 1fba77df7f62..f884652b4323 100644
--- a/tools/testing/selftests/mm/mlock-random-test.c
+++ b/tools/testing/selftests/mm/mlock-random-test.c
@@ -86,7 +86,7 @@ int get_proc_locked_vm_size(void)
int get_proc_page_size(unsigned long addr)
{
FILE *smaps;
- char *line;
+ char *line = NULL;
unsigned long mmupage_size = 0;
size_t size;
^ permalink raw reply related [flat|nested] 2+ messages in thread