Compare commits
95 commits
d37421e655
...
edd435390c
Author | SHA1 | Date | |
---|---|---|---|
|
edd435390c | ||
|
010b07d11e | ||
|
2ab8930ec1 | ||
|
9852d85ec9 | ||
|
3f749befb0 | ||
|
e7ed343658 | ||
|
907537f570 | ||
|
b81b78dacc | ||
|
3ed7df0852 | ||
|
9f9a534724 | ||
|
3a5895e3ac | ||
|
0b0f0ad93c | ||
|
a6508079b1 | ||
|
e057a290ef | ||
|
d50d7a5fa4 | ||
|
1c0ee43b2c | ||
|
9773547b16 | ||
|
a3581ca35d | ||
|
f8911ad88d | ||
|
cf49f8a8c2 | ||
|
fd65378db9 | ||
|
8d65b15f8d | ||
|
5612daafb7 | ||
|
7c980a43e9 | ||
|
431312b59c | ||
|
49fd90b2cc | ||
|
9104fc1928 | ||
|
1e0272ef47 | ||
|
3672bda8f5 | ||
|
22a507d68e | ||
|
b29c30ab48 | ||
|
dc5bfdf8ea | ||
|
3125c95ea6 | ||
|
951dd86e7c | ||
|
2a1df87346 | ||
|
40d40c6bea | ||
|
c6040447c5 | ||
|
18c520f408 | ||
|
0696a18a8c | ||
|
51b7cc7c0f | ||
|
4a8f8fafbd | ||
|
f890c8513f | ||
|
26de8614d8 | ||
|
54595f2807 | ||
|
0c8d604dea | ||
|
6d3405415f | ||
|
bfc4a245a7 | ||
|
f2990f8630 | ||
|
5d69d5a00f | ||
|
7eb4a319db | ||
|
6d12d7ace9 | ||
|
5232544ea3 | ||
|
4116ab5e8a | ||
|
c13c196d5e | ||
|
263dbd3cc8 | ||
|
dc09f007ca | ||
|
0d97651b75 | ||
|
e92d87c9c5 | ||
|
39d7d6177f | ||
|
0e4ed48292 | ||
|
39c3aad43f | ||
|
359aeb8648 | ||
|
b071c1a909 | ||
|
eeb85c658e | ||
|
1af9af1f8a | ||
|
0a3c84f716 | ||
|
d1a2ef63fc | ||
|
05ab4e7846 | ||
|
fc318cac66 | ||
|
93bcc5f398 | ||
|
95474648b8 | ||
|
e7d67f3f9f | ||
|
4616a4b3cb | ||
|
6e4c825f26 | ||
|
fc1ddda330 | ||
|
9634bb0708 | ||
|
f81eaf0838 | ||
|
a141c17a54 | ||
|
bba20b894e | ||
|
4708c9332d | ||
|
a8598aefae | ||
|
24d7071d96 | ||
|
0c40f079f1 | ||
|
0557f49870 | ||
|
c7c846fa94 | ||
|
fa557da6b0 | ||
|
d2ce0e5ab5 | ||
|
571d81b482 | ||
|
34f04a9b6e | ||
|
57bada8a5e | ||
|
e88ed59432 | ||
|
45fad027df | ||
|
e368400694 | ||
|
b112947ffc | ||
|
3d882cca73 |
107 changed files with 1076 additions and 568 deletions
|
@ -31,6 +31,15 @@ kselftest runs as a userspace process. Tests that can be written/run in
|
|||
userspace may wish to use the `Test Harness`_. Tests that need to be
|
||||
run in kernel space may wish to use a `Test Module`_.
|
||||
|
||||
Documentation on the tests
|
||||
==========================
|
||||
|
||||
For documentation on the kselftests themselves, see:
|
||||
|
||||
.. toctree::
|
||||
|
||||
testing-devices
|
||||
|
||||
Running the selftests (hotplug tests are run in limited mode)
|
||||
=============================================================
|
||||
|
||||
|
|
47
Documentation/dev-tools/testing-devices.rst
Normal file
47
Documentation/dev-tools/testing-devices.rst
Normal file
|
@ -0,0 +1,47 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
.. Copyright (c) 2024 Collabora Ltd
|
||||
|
||||
=============================
|
||||
Device testing with kselftest
|
||||
=============================
|
||||
|
||||
|
||||
There are a few different kselftests available for testing devices generically,
|
||||
with some overlap in coverage and different requirements. This document aims to
|
||||
give an overview of each one.
|
||||
|
||||
Note: Paths in this document are relative to the kselftest folder
|
||||
(``tools/testing/selftests``).
|
||||
|
||||
Device oriented kselftests:
|
||||
|
||||
* Devicetree (``dt``)
|
||||
|
||||
* **Coverage**: Probe status for devices described in Devicetree
|
||||
* **Requirements**: None
|
||||
|
||||
* Error logs (``devices/error_logs``)
|
||||
|
||||
* **Coverage**: Error (or more critical) log messages presence coming from any
|
||||
device
|
||||
* **Requirements**: None
|
||||
|
||||
* Discoverable bus (``devices/probe``)
|
||||
|
||||
* **Coverage**: Presence and probe status of USB or PCI devices that have been
|
||||
described in the reference file
|
||||
* **Requirements**: Manually describe the devices that should be tested in a
|
||||
YAML reference file (see ``devices/probe/boards/google,spherion.yaml`` for
|
||||
an example)
|
||||
|
||||
* Exist (``devices/exist``)
|
||||
|
||||
* **Coverage**: Presence of all devices
|
||||
* **Requirements**: Generate the reference (see ``devices/exist/README.rst``
|
||||
for details) on a known-good kernel
|
||||
|
||||
Therefore, the suggestion is to enable the error log and devicetree tests on all
|
||||
(DT-based) platforms, since they don't have any requirements. Then to greatly
|
||||
improve coverage, generate the reference for each platform and enable the exist
|
||||
test. The discoverable bus test can be used to verify the probe status of
|
||||
specific USB or PCI devices, but is probably not worth it for most cases.
|
|
@ -17,9 +17,15 @@ description: |
|
|||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- mediatek,mt8195-adsp-mbox
|
||||
oneOf:
|
||||
- enum:
|
||||
- mediatek,mt8186-adsp-mbox
|
||||
- mediatek,mt8195-adsp-mbox
|
||||
- items:
|
||||
- enum:
|
||||
- mediatek,mt8188-adsp-mbox
|
||||
- const: mediatek,mt8186-adsp-mbox
|
||||
|
||||
|
||||
"#mbox-cells":
|
||||
const: 0
|
||||
|
|
|
@ -24,7 +24,9 @@ properties:
|
|||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- qcom,qcs8300-ipcc
|
||||
- qcom,qdu1000-ipcc
|
||||
- qcom,sa8255p-ipcc
|
||||
- qcom,sa8775p-ipcc
|
||||
- qcom,sc7280-ipcc
|
||||
- qcom,sc8280xp-ipcc
|
||||
|
|
4
Makefile
4
Makefile
|
@ -1,8 +1,8 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 11
|
||||
PATCHLEVEL = 12
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION =
|
||||
EXTRAVERSION = -rc1
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
@ -31,6 +31,8 @@ void cpu_emergency_register_virt_callback(cpu_emergency_virt_cb *callback);
|
|||
void cpu_emergency_unregister_virt_callback(cpu_emergency_virt_cb *callback);
|
||||
void cpu_emergency_disable_virtualization(void);
|
||||
#else
|
||||
static inline void cpu_emergency_register_virt_callback(cpu_emergency_virt_cb *callback) {}
|
||||
static inline void cpu_emergency_unregister_virt_callback(cpu_emergency_virt_cb *callback) {}
|
||||
static inline void cpu_emergency_disable_virtualization(void) {}
|
||||
#endif /* CONFIG_KVM_INTEL || CONFIG_KVM_AMD */
|
||||
|
||||
|
|
|
@ -782,6 +782,7 @@ config I2C_JZ4780
|
|||
config I2C_KEBA
|
||||
tristate "KEBA I2C controller support"
|
||||
depends on HAS_IOMEM
|
||||
depends on KEBA_CP500 || COMPILE_TEST
|
||||
select AUXILIARY_BUS
|
||||
help
|
||||
This driver supports the I2C controller found in KEBA system FPGA
|
||||
|
|
|
@ -523,6 +523,7 @@ int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev)
|
|||
|
||||
void __i2c_dw_disable(struct dw_i2c_dev *dev)
|
||||
{
|
||||
struct i2c_timings *t = &dev->timings;
|
||||
unsigned int raw_intr_stats;
|
||||
unsigned int enable;
|
||||
int timeout = 100;
|
||||
|
@ -535,6 +536,19 @@ void __i2c_dw_disable(struct dw_i2c_dev *dev)
|
|||
|
||||
abort_needed = raw_intr_stats & DW_IC_INTR_MST_ON_HOLD;
|
||||
if (abort_needed) {
|
||||
if (!(enable & DW_IC_ENABLE_ENABLE)) {
|
||||
regmap_write(dev->map, DW_IC_ENABLE, DW_IC_ENABLE_ENABLE);
|
||||
/*
|
||||
* Wait 10 times the signaling period of the highest I2C
|
||||
* transfer supported by the driver (for 400KHz this is
|
||||
* 25us) to ensure the I2C ENABLE bit is already set
|
||||
* as described in the DesignWare I2C databook.
|
||||
*/
|
||||
fsleep(DIV_ROUND_CLOSEST_ULL(10 * MICRO, t->bus_freq_hz));
|
||||
/* Set ENABLE bit before setting ABORT */
|
||||
enable |= DW_IC_ENABLE_ENABLE;
|
||||
}
|
||||
|
||||
regmap_write(dev->map, DW_IC_ENABLE, enable | DW_IC_ENABLE_ABORT);
|
||||
ret = regmap_read_poll_timeout(dev->map, DW_IC_ENABLE, enable,
|
||||
!(enable & DW_IC_ENABLE_ABORT), 10,
|
||||
|
|
|
@ -108,6 +108,7 @@
|
|||
DW_IC_INTR_RX_UNDER | \
|
||||
DW_IC_INTR_RD_REQ)
|
||||
|
||||
#define DW_IC_ENABLE_ENABLE BIT(0)
|
||||
#define DW_IC_ENABLE_ABORT BIT(1)
|
||||
|
||||
#define DW_IC_STATUS_ACTIVITY BIT(0)
|
||||
|
|
|
@ -271,6 +271,34 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
|
|||
__i2c_dw_write_intr_mask(dev, DW_IC_INTR_MASTER_MASK);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function waits for the controller to be idle before disabling I2C
|
||||
* When the controller is not in the IDLE state, the MST_ACTIVITY bit
|
||||
* (IC_STATUS[5]) is set.
|
||||
*
|
||||
* Values:
|
||||
* 0x1 (ACTIVE): Controller not idle
|
||||
* 0x0 (IDLE): Controller is idle
|
||||
*
|
||||
* The function is called after completing the current transfer.
|
||||
*
|
||||
* Returns:
|
||||
* False when the controller is in the IDLE state.
|
||||
* True when the controller is in the ACTIVE state.
|
||||
*/
|
||||
static bool i2c_dw_is_controller_active(struct dw_i2c_dev *dev)
|
||||
{
|
||||
u32 status;
|
||||
|
||||
regmap_read(dev->map, DW_IC_STATUS, &status);
|
||||
if (!(status & DW_IC_STATUS_MASTER_ACTIVITY))
|
||||
return false;
|
||||
|
||||
return regmap_read_poll_timeout(dev->map, DW_IC_STATUS, status,
|
||||
!(status & DW_IC_STATUS_MASTER_ACTIVITY),
|
||||
1100, 20000) != 0;
|
||||
}
|
||||
|
||||
static int i2c_dw_check_stopbit(struct dw_i2c_dev *dev)
|
||||
{
|
||||
u32 val;
|
||||
|
@ -806,6 +834,16 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
|
|||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* This happens rarely (~1:500) and is hard to reproduce. Debug trace
|
||||
* showed that IC_STATUS had value of 0x23 when STOP_DET occurred,
|
||||
* if disable IC_ENABLE.ENABLE immediately that can result in
|
||||
* IC_RAW_INTR_STAT.MASTER_ON_HOLD holding SCL low. Check if
|
||||
* controller is still ACTIVE before disabling I2C.
|
||||
*/
|
||||
if (i2c_dw_is_controller_active(dev))
|
||||
dev_err(dev->dev, "controller active\n");
|
||||
|
||||
/*
|
||||
* We must disable the adapter before returning and signaling the end
|
||||
* of the current transfer. Otherwise the hardware might continue
|
||||
|
|
|
@ -550,11 +550,12 @@ static int synquacer_i2c_probe(struct platform_device *pdev)
|
|||
device_property_read_u32(&pdev->dev, "socionext,pclk-rate",
|
||||
&i2c->pclkrate);
|
||||
|
||||
pclk = devm_clk_get_enabled(&pdev->dev, "pclk");
|
||||
pclk = devm_clk_get_optional_enabled(&pdev->dev, "pclk");
|
||||
if (IS_ERR(pclk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(pclk),
|
||||
"failed to get and enable clock\n");
|
||||
|
||||
if (pclk)
|
||||
i2c->pclkrate = clk_get_rate(pclk);
|
||||
|
||||
if (i2c->pclkrate < SYNQUACER_I2C_MIN_CLK_RATE ||
|
||||
|
|
|
@ -1337,8 +1337,8 @@ static int xiic_i2c_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
err_pm_disable:
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ config ARM_MHU_V2
|
|||
|
||||
config ARM_MHU_V3
|
||||
tristate "ARM MHUv3 Mailbox"
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
depends on HAS_IOMEM || COMPILE_TEST
|
||||
depends on OF
|
||||
help
|
||||
|
@ -73,7 +74,7 @@ config ARMADA_37XX_RWTM_MBOX
|
|||
|
||||
config OMAP2PLUS_MBOX
|
||||
tristate "OMAP2+ Mailbox framework support"
|
||||
depends on ARCH_OMAP2PLUS || ARCH_K3
|
||||
depends on ARCH_OMAP2PLUS || ARCH_K3 || COMPILE_TEST
|
||||
help
|
||||
Mailbox implementation for OMAP family chips with hardware for
|
||||
interprocessor communication involving DSP, IVA1.0 and IVA2 in
|
||||
|
|
|
@ -145,7 +145,8 @@ static int bcm2835_mbox_probe(struct platform_device *pdev)
|
|||
spin_lock_init(&mbox->lock);
|
||||
|
||||
ret = devm_request_irq(dev, irq_of_parse_and_map(dev->of_node, 0),
|
||||
bcm2835_mbox_irq, 0, dev_name(dev), mbox);
|
||||
bcm2835_mbox_irq, IRQF_NO_SUSPEND, dev_name(dev),
|
||||
mbox);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to register a mailbox IRQ handler: %d\n",
|
||||
ret);
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#define IMX_MU_SCU_CHANS 6
|
||||
/* TX0/RX0 */
|
||||
#define IMX_MU_S4_CHANS 2
|
||||
#define IMX_MU_CHAN_NAME_SIZE 20
|
||||
#define IMX_MU_CHAN_NAME_SIZE 32
|
||||
|
||||
#define IMX_MU_V2_PAR_OFF 0x4
|
||||
#define IMX_MU_V2_TR_MASK GENMASK(7, 0)
|
||||
|
@ -782,7 +782,7 @@ static int imx_mu_init_generic(struct imx_mu_priv *priv)
|
|||
cp->chan = &priv->mbox_chans[i];
|
||||
priv->mbox_chans[i].con_priv = cp;
|
||||
snprintf(cp->irq_desc, sizeof(cp->irq_desc),
|
||||
"imx_mu_chan[%i-%i]", cp->type, cp->idx);
|
||||
"%s[%i-%i]", dev_name(priv->dev), cp->type, cp->idx);
|
||||
}
|
||||
|
||||
priv->mbox.num_chans = IMX_MU_CHANS;
|
||||
|
@ -819,7 +819,7 @@ static int imx_mu_init_specific(struct imx_mu_priv *priv)
|
|||
cp->chan = &priv->mbox_chans[i];
|
||||
priv->mbox_chans[i].con_priv = cp;
|
||||
snprintf(cp->irq_desc, sizeof(cp->irq_desc),
|
||||
"imx_mu_chan[%i-%i]", cp->type, cp->idx);
|
||||
"%s[%i-%i]", dev_name(priv->dev), cp->type, cp->idx);
|
||||
}
|
||||
|
||||
priv->mbox.num_chans = num_chans;
|
||||
|
|
|
@ -450,30 +450,20 @@ struct mbox_chan *mbox_request_channel_byname(struct mbox_client *cl,
|
|||
const char *name)
|
||||
{
|
||||
struct device_node *np = cl->dev->of_node;
|
||||
struct property *prop;
|
||||
const char *mbox_name;
|
||||
int index = 0;
|
||||
int index;
|
||||
|
||||
if (!np) {
|
||||
dev_err(cl->dev, "%s() currently only supports DT\n", __func__);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (!of_get_property(np, "mbox-names", NULL)) {
|
||||
dev_err(cl->dev,
|
||||
"%s() requires an \"mbox-names\" property\n", __func__);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
of_property_for_each_string(np, "mbox-names", prop, mbox_name) {
|
||||
if (!strncmp(name, mbox_name, strlen(name)))
|
||||
return mbox_request_channel(cl, index);
|
||||
index++;
|
||||
}
|
||||
|
||||
index = of_property_match_string(np, "mbox-names", name);
|
||||
if (index < 0) {
|
||||
dev_err(cl->dev, "%s() could not locate channel named \"%s\"\n",
|
||||
__func__, name);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
return mbox_request_channel(cl, index);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mbox_request_channel_byname);
|
||||
|
||||
|
|
|
@ -603,7 +603,7 @@ static struct platform_driver omap_mbox_driver = {
|
|||
.driver = {
|
||||
.name = "omap-mailbox",
|
||||
.pm = &omap_mbox_pm_ops,
|
||||
.of_match_table = of_match_ptr(omap_mailbox_of_match),
|
||||
.of_match_table = omap_mailbox_of_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(omap_mbox_driver);
|
||||
|
|
|
@ -159,7 +159,7 @@ static const struct of_device_id rockchip_mbox_of_match[] = {
|
|||
{ .compatible = "rockchip,rk3368-mailbox", .data = &rk3368_drv_data},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rockchp_mbox_of_match);
|
||||
MODULE_DEVICE_TABLE(of, rockchip_mbox_of_match);
|
||||
|
||||
static int rockchip_mbox_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
|
|
@ -62,7 +62,6 @@ struct sprd_mbox_priv {
|
|||
void __iomem *outbox_base;
|
||||
/* Base register address for supplementary outbox */
|
||||
void __iomem *supp_base;
|
||||
struct clk *clk;
|
||||
u32 outbox_fifo_depth;
|
||||
|
||||
struct mutex lock;
|
||||
|
@ -291,19 +290,13 @@ static const struct mbox_chan_ops sprd_mbox_ops = {
|
|||
.shutdown = sprd_mbox_shutdown,
|
||||
};
|
||||
|
||||
static void sprd_mbox_disable(void *data)
|
||||
{
|
||||
struct sprd_mbox_priv *priv = data;
|
||||
|
||||
clk_disable_unprepare(priv->clk);
|
||||
}
|
||||
|
||||
static int sprd_mbox_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct sprd_mbox_priv *priv;
|
||||
int ret, inbox_irq, outbox_irq, supp_irq;
|
||||
unsigned long id, supp;
|
||||
struct clk *clk;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
|
@ -331,20 +324,10 @@ static int sprd_mbox_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(priv->outbox_base))
|
||||
return PTR_ERR(priv->outbox_base);
|
||||
|
||||
priv->clk = devm_clk_get(dev, "enable");
|
||||
if (IS_ERR(priv->clk)) {
|
||||
clk = devm_clk_get_enabled(dev, "enable");
|
||||
if (IS_ERR(clk)) {
|
||||
dev_err(dev, "failed to get mailbox clock\n");
|
||||
return PTR_ERR(priv->clk);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(priv->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, sprd_mbox_disable, priv);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to add mailbox disable action\n");
|
||||
return ret;
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
|
||||
inbox_irq = platform_get_irq_byname(pdev, "inbox");
|
||||
|
|
|
@ -1609,7 +1609,7 @@ mptctl_eventreport (MPT_ADAPTER *ioc, unsigned long arg)
|
|||
maxEvents = numBytes/sizeof(MPT_IOCTL_EVENTS);
|
||||
|
||||
|
||||
max = MPTCTL_EVENT_LOG_SIZE < maxEvents ? MPTCTL_EVENT_LOG_SIZE : maxEvents;
|
||||
max = min(maxEvents, MPTCTL_EVENT_LOG_SIZE);
|
||||
|
||||
/* If fewer than 1 event is requested, there must have
|
||||
* been some type of error.
|
||||
|
|
|
@ -330,8 +330,7 @@ config STM32_RPROC
|
|||
config TI_K3_DSP_REMOTEPROC
|
||||
tristate "TI K3 DSP remoteproc support"
|
||||
depends on ARCH_K3
|
||||
select MAILBOX
|
||||
select OMAP2PLUS_MBOX
|
||||
depends on OMAP2PLUS_MBOX
|
||||
help
|
||||
Say m here to support TI's C66x and C71x DSP remote processor
|
||||
subsystems on various TI K3 family of SoCs through the remote
|
||||
|
@ -356,8 +355,7 @@ config TI_K3_M4_REMOTEPROC
|
|||
config TI_K3_R5_REMOTEPROC
|
||||
tristate "TI K3 R5 remoteproc support"
|
||||
depends on ARCH_K3
|
||||
select MAILBOX
|
||||
select OMAP2PLUS_MBOX
|
||||
depends on OMAP2PLUS_MBOX
|
||||
help
|
||||
Say m here to support TI's R5F remote processor subsystems
|
||||
on various TI K3 family of SoCs through the remote processor
|
||||
|
|
|
@ -485,7 +485,6 @@ struct cxgbi_device {
|
|||
unsigned char nmtus;
|
||||
unsigned char nports;
|
||||
struct pci_dev *pdev;
|
||||
struct dentry *debugfs_root;
|
||||
struct iscsi_transport *itp;
|
||||
struct module *owner;
|
||||
|
||||
|
@ -499,7 +498,6 @@ struct cxgbi_device {
|
|||
unsigned int rxq_idx_cntr;
|
||||
struct cxgbi_ports_map pmap;
|
||||
|
||||
void (*dev_ddp_cleanup)(struct cxgbi_device *);
|
||||
struct cxgbi_ppm* (*cdev2ppm)(struct cxgbi_device *);
|
||||
int (*csk_ddp_set_map)(struct cxgbi_ppm *, struct cxgbi_sock *,
|
||||
struct cxgbi_task_tag_info *);
|
||||
|
@ -512,7 +510,6 @@ struct cxgbi_device {
|
|||
unsigned int, int);
|
||||
|
||||
void (*csk_release_offload_resources)(struct cxgbi_sock *);
|
||||
int (*csk_rx_pdu_ready)(struct cxgbi_sock *, struct sk_buff *);
|
||||
u32 (*csk_send_rx_credits)(struct cxgbi_sock *, u32);
|
||||
int (*csk_push_tx_frames)(struct cxgbi_sock *, int);
|
||||
void (*csk_send_abort_req)(struct cxgbi_sock *);
|
||||
|
|
|
@ -2421,7 +2421,7 @@ static void slot_complete_v3_hw(struct hisi_hba *hisi_hba,
|
|||
spin_lock_irqsave(&device->done_lock, flags);
|
||||
if (test_bit(SAS_HA_FROZEN, &ha->state)) {
|
||||
spin_unlock_irqrestore(&device->done_lock, flags);
|
||||
dev_info(dev, "slot complete: task(%pK) ignored\n ",
|
||||
dev_info(dev, "slot complete: task(%pK) ignored\n",
|
||||
task);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ static unsigned int default_timeout = IBMVFC_DEFAULT_TIMEOUT;
|
|||
static u64 max_lun = IBMVFC_MAX_LUN;
|
||||
static unsigned int max_targets = IBMVFC_MAX_TARGETS;
|
||||
static unsigned int max_requests = IBMVFC_MAX_REQUESTS_DEFAULT;
|
||||
static u16 max_sectors = IBMVFC_MAX_SECTORS;
|
||||
static u16 scsi_qdepth = IBMVFC_SCSI_QDEPTH;
|
||||
static unsigned int disc_threads = IBMVFC_MAX_DISC_THREADS;
|
||||
static unsigned int ibmvfc_debug = IBMVFC_DEBUG;
|
||||
|
@ -83,6 +84,9 @@ MODULE_PARM_DESC(default_timeout,
|
|||
module_param_named(max_requests, max_requests, uint, S_IRUGO);
|
||||
MODULE_PARM_DESC(max_requests, "Maximum requests for this adapter. "
|
||||
"[Default=" __stringify(IBMVFC_MAX_REQUESTS_DEFAULT) "]");
|
||||
module_param_named(max_sectors, max_sectors, ushort, S_IRUGO);
|
||||
MODULE_PARM_DESC(max_sectors, "Maximum sectors for this adapter. "
|
||||
"[Default=" __stringify(IBMVFC_MAX_SECTORS) "]");
|
||||
module_param_named(scsi_qdepth, scsi_qdepth, ushort, S_IRUGO);
|
||||
MODULE_PARM_DESC(scsi_qdepth, "Maximum scsi command depth per adapter queue. "
|
||||
"[Default=" __stringify(IBMVFC_SCSI_QDEPTH) "]");
|
||||
|
@ -1494,7 +1498,7 @@ static void ibmvfc_set_login_info(struct ibmvfc_host *vhost)
|
|||
memset(login_info, 0, sizeof(*login_info));
|
||||
|
||||
login_info->ostype = cpu_to_be32(IBMVFC_OS_LINUX);
|
||||
login_info->max_dma_len = cpu_to_be64(IBMVFC_MAX_SECTORS << 9);
|
||||
login_info->max_dma_len = cpu_to_be64(max_sectors << 9);
|
||||
login_info->max_payload = cpu_to_be32(sizeof(struct ibmvfc_fcp_cmd_iu));
|
||||
login_info->max_response = cpu_to_be32(sizeof(struct ibmvfc_fcp_rsp));
|
||||
login_info->partition_num = cpu_to_be32(vhost->partition_number);
|
||||
|
@ -5230,7 +5234,7 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt)
|
|||
}
|
||||
|
||||
vhost->logged_in = 1;
|
||||
npiv_max_sectors = min((uint)(be64_to_cpu(rsp->max_dma_len) >> 9), IBMVFC_MAX_SECTORS);
|
||||
npiv_max_sectors = min((uint)(be64_to_cpu(rsp->max_dma_len) >> 9), max_sectors);
|
||||
dev_info(vhost->dev, "Host partition: %s, device: %s %s %s max sectors %u\n",
|
||||
rsp->partition_name, rsp->device_name, rsp->port_loc_code,
|
||||
rsp->drc_name, npiv_max_sectors);
|
||||
|
@ -6329,7 +6333,7 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
|
|||
shost->can_queue = scsi_qdepth;
|
||||
shost->max_lun = max_lun;
|
||||
shost->max_id = max_targets;
|
||||
shost->max_sectors = IBMVFC_MAX_SECTORS;
|
||||
shost->max_sectors = max_sectors;
|
||||
shost->max_cmd_len = IBMVFC_MAX_CDB_LEN;
|
||||
shost->unique_id = shost->host_no;
|
||||
shost->nr_hw_queues = mq_enabled ? min(max_scsi_queues, nr_scsi_hw_queues) : 1;
|
||||
|
@ -6556,6 +6560,7 @@ static struct fc_function_template ibmvfc_transport_functions = {
|
|||
**/
|
||||
static int __init ibmvfc_module_init(void)
|
||||
{
|
||||
int min_max_sectors = PAGE_SIZE >> 9;
|
||||
int rc;
|
||||
|
||||
if (!firmware_has_feature(FW_FEATURE_VIO))
|
||||
|
@ -6564,6 +6569,16 @@ static int __init ibmvfc_module_init(void)
|
|||
printk(KERN_INFO IBMVFC_NAME": IBM Virtual Fibre Channel Driver version: %s %s\n",
|
||||
IBMVFC_DRIVER_VERSION, IBMVFC_DRIVER_DATE);
|
||||
|
||||
/*
|
||||
* Range check the max_sectors module parameter. The upper bounds is
|
||||
* implicity checked since the parameter is a ushort.
|
||||
*/
|
||||
if (max_sectors < min_max_sectors) {
|
||||
printk(KERN_ERR IBMVFC_NAME ": max_sectors must be at least %d.\n",
|
||||
min_max_sectors);
|
||||
max_sectors = min_max_sectors;
|
||||
}
|
||||
|
||||
ibmvfc_transport_template = fc_attach_transport(&ibmvfc_transport_functions);
|
||||
if (!ibmvfc_transport_template)
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#define IBMVFC_DEBUG 0
|
||||
#define IBMVFC_MAX_TARGETS 1024
|
||||
#define IBMVFC_MAX_LUN 0xffffffff
|
||||
#define IBMVFC_MAX_SECTORS 0xffffu
|
||||
#define IBMVFC_MAX_SECTORS 2048
|
||||
#define IBMVFC_MAX_DISC_THREADS 4
|
||||
#define IBMVFC_TGT_MEMPOOL_SZ 64
|
||||
#define IBMVFC_MAX_CMDS_PER_LUN 64
|
||||
|
|
|
@ -3208,6 +3208,9 @@ lpfc_bsg_diag_loopback_run(struct bsg_job *job)
|
|||
cmdiocbq->num_bdes = num_bde;
|
||||
cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC;
|
||||
cmdiocbq->cmd_flag |= LPFC_IO_LOOPBACK;
|
||||
if (phba->cfg_vmid_app_header)
|
||||
cmdiocbq->cmd_flag |= LPFC_IO_VMID;
|
||||
|
||||
cmdiocbq->vport = phba->pport;
|
||||
cmdiocbq->cmd_cmpl = NULL;
|
||||
cmdiocbq->bpl_dmabuf = txbmp;
|
||||
|
|
|
@ -1572,8 +1572,8 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
}
|
||||
}
|
||||
} else
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"3065 GFT_ID failed x%08x\n", ulp_status);
|
||||
lpfc_vlog_msg(vport, KERN_WARNING, LOG_DISCOVERY,
|
||||
"3065 GFT_ID status x%08x\n", ulp_status);
|
||||
|
||||
out:
|
||||
lpfc_ct_free_iocb(phba, cmdiocb);
|
||||
|
@ -1647,6 +1647,18 @@ lpfc_cmpl_ct(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
}
|
||||
|
||||
out:
|
||||
/* If the caller wanted a synchronous DA_ID completion, signal the
|
||||
* wait obj and clear flag to reset the vport.
|
||||
*/
|
||||
if (ndlp->save_flags & NLP_WAIT_FOR_DA_ID) {
|
||||
if (ndlp->da_id_waitq)
|
||||
wake_up(ndlp->da_id_waitq);
|
||||
}
|
||||
|
||||
spin_lock_irq(&ndlp->lock);
|
||||
ndlp->save_flags &= ~NLP_WAIT_FOR_DA_ID;
|
||||
spin_unlock_irq(&ndlp->lock);
|
||||
|
||||
lpfc_ct_free_iocb(phba, cmdiocb);
|
||||
lpfc_nlp_put(ndlp);
|
||||
return;
|
||||
|
@ -2246,7 +2258,7 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
}
|
||||
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
|
||||
"0229 FDMI cmd %04x failed, latt = %d "
|
||||
"0229 FDMI cmd %04x latt = %d "
|
||||
"ulp_status: x%x, rid x%x\n",
|
||||
be16_to_cpu(fdmi_cmd), latt, ulp_status,
|
||||
ulp_word4);
|
||||
|
@ -2263,9 +2275,9 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
/* Check for a CT LS_RJT response */
|
||||
cmd = be16_to_cpu(fdmi_cmd);
|
||||
if (be16_to_cpu(fdmi_rsp) == SLI_CT_RESPONSE_FS_RJT) {
|
||||
/* FDMI rsp failed */
|
||||
/* Log FDMI reject */
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY | LOG_ELS,
|
||||
"0220 FDMI cmd failed FS_RJT Data: x%x", cmd);
|
||||
"0220 FDMI cmd FS_RJT Data: x%x", cmd);
|
||||
|
||||
/* Should we fallback to FDMI-2 / FDMI-1 ? */
|
||||
switch (cmd) {
|
||||
|
|
|
@ -90,6 +90,8 @@ enum lpfc_nlp_save_flags {
|
|||
NLP_IN_RECOV_POST_DEV_LOSS = 0x1,
|
||||
/* wait for outstanding LOGO to cmpl */
|
||||
NLP_WAIT_FOR_LOGO = 0x2,
|
||||
/* wait for outstanding DA_ID to finish */
|
||||
NLP_WAIT_FOR_DA_ID = 0x4
|
||||
};
|
||||
|
||||
struct lpfc_nodelist {
|
||||
|
@ -159,7 +161,12 @@ struct lpfc_nodelist {
|
|||
uint32_t nvme_fb_size; /* NVME target's supported byte cnt */
|
||||
#define NVME_FB_BIT_SHIFT 9 /* PRLI Rsp first burst in 512B units. */
|
||||
uint32_t nlp_defer_did;
|
||||
|
||||
/* These wait objects are NPIV specific. These IOs must complete
|
||||
* synchronously.
|
||||
*/
|
||||
wait_queue_head_t *logo_waitq;
|
||||
wait_queue_head_t *da_id_waitq;
|
||||
};
|
||||
|
||||
struct lpfc_node_rrq {
|
||||
|
|
|
@ -979,7 +979,7 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
phba->fcoe_cvl_eventtag_attn =
|
||||
phba->fcoe_cvl_eventtag;
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_FIP | LOG_ELS,
|
||||
"2611 FLOGI failed on FCF (x%x), "
|
||||
"2611 FLOGI FCF (x%x), "
|
||||
"status:x%x/x%x, tmo:x%x, perform "
|
||||
"roundrobin FCF failover\n",
|
||||
phba->fcf.current_rec.fcf_indx,
|
||||
|
@ -997,8 +997,8 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
if (!(ulp_status == IOSTAT_LOCAL_REJECT &&
|
||||
((ulp_word4 & IOERR_PARAM_MASK) ==
|
||||
IOERR_LOOP_OPEN_FAILURE)))
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"2858 FLOGI failure Status:x%x/x%x TMO"
|
||||
lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS,
|
||||
"2858 FLOGI Status:x%x/x%x TMO"
|
||||
":x%x Data x%lx x%x\n",
|
||||
ulp_status, ulp_word4, tmo,
|
||||
phba->hba_flag, phba->fcf.fcf_flag);
|
||||
|
@ -1023,7 +1023,7 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
lpfc_nlp_put(ndlp);
|
||||
|
||||
lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS,
|
||||
"0150 FLOGI failure Status:x%x/x%x "
|
||||
"0150 FLOGI Status:x%x/x%x "
|
||||
"xri x%x TMO:x%x refcnt %d\n",
|
||||
ulp_status, ulp_word4, cmdiocb->sli4_xritag,
|
||||
tmo, kref_read(&ndlp->kref));
|
||||
|
@ -1032,9 +1032,9 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
if (!(ulp_status == IOSTAT_LOCAL_REJECT &&
|
||||
((ulp_word4 & IOERR_PARAM_MASK) ==
|
||||
IOERR_LOOP_OPEN_FAILURE))) {
|
||||
/* FLOGI failure */
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"0100 FLOGI failure Status:x%x/x%x "
|
||||
/* Warn FLOGI status */
|
||||
lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS,
|
||||
"0100 FLOGI Status:x%x/x%x "
|
||||
"TMO:x%x\n",
|
||||
ulp_status, ulp_word4, tmo);
|
||||
goto flogifail;
|
||||
|
@ -1964,13 +1964,13 @@ lpfc_cmpl_els_rrq(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
|
||||
if (ulp_status) {
|
||||
/* Check for retry */
|
||||
/* RRQ failed Don't print the vport to vport rjts */
|
||||
/* Warn RRQ status Don't print the vport to vport rjts */
|
||||
if (ulp_status != IOSTAT_LS_RJT ||
|
||||
(((ulp_word4) >> 16 != LSRJT_INVALID_CMD) &&
|
||||
((ulp_word4) >> 16 != LSRJT_UNABLE_TPC)) ||
|
||||
(phba)->pport->cfg_log_verbose & LOG_ELS)
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"2881 RRQ failure DID:%06X Status:"
|
||||
lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS,
|
||||
"2881 RRQ DID:%06X Status:"
|
||||
"x%x/x%x\n",
|
||||
ndlp->nlp_DID, ulp_status,
|
||||
ulp_word4);
|
||||
|
@ -2077,13 +2077,13 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
}
|
||||
goto out;
|
||||
}
|
||||
/* PLOGI failed Don't print the vport to vport rjts */
|
||||
/* Warn PLOGI status Don't print the vport to vport rjts */
|
||||
if (ulp_status != IOSTAT_LS_RJT ||
|
||||
(((ulp_word4) >> 16 != LSRJT_INVALID_CMD) &&
|
||||
((ulp_word4) >> 16 != LSRJT_UNABLE_TPC)) ||
|
||||
(phba)->pport->cfg_log_verbose & LOG_ELS)
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"2753 PLOGI failure DID:%06X "
|
||||
lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS,
|
||||
"2753 PLOGI DID:%06X "
|
||||
"Status:x%x/x%x\n",
|
||||
ndlp->nlp_DID, ulp_status,
|
||||
ulp_word4);
|
||||
|
@ -2323,7 +2323,6 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
struct lpfc_vport *vport = cmdiocb->vport;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
char *mode;
|
||||
u32 loglevel;
|
||||
u32 ulp_status;
|
||||
u32 ulp_word4;
|
||||
bool release_node = false;
|
||||
|
@ -2372,17 +2371,14 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
* could be expected.
|
||||
*/
|
||||
if (test_bit(FC_FABRIC, &vport->fc_flag) ||
|
||||
vport->cfg_enable_fc4_type != LPFC_ENABLE_BOTH) {
|
||||
mode = KERN_ERR;
|
||||
loglevel = LOG_TRACE_EVENT;
|
||||
} else {
|
||||
vport->cfg_enable_fc4_type != LPFC_ENABLE_BOTH)
|
||||
mode = KERN_WARNING;
|
||||
else
|
||||
mode = KERN_INFO;
|
||||
loglevel = LOG_ELS;
|
||||
}
|
||||
|
||||
/* PRLI failed */
|
||||
lpfc_printf_vlog(vport, mode, loglevel,
|
||||
"2754 PRLI failure DID:%06X Status:x%x/x%x, "
|
||||
/* Warn PRLI status */
|
||||
lpfc_printf_vlog(vport, mode, LOG_ELS,
|
||||
"2754 PRLI DID:%06X Status:x%x/x%x, "
|
||||
"data: x%x x%x x%x\n",
|
||||
ndlp->nlp_DID, ulp_status,
|
||||
ulp_word4, ndlp->nlp_state,
|
||||
|
@ -2854,9 +2850,9 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
}
|
||||
goto out;
|
||||
}
|
||||
/* ADISC failed */
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"2755 ADISC failure DID:%06X Status:x%x/x%x\n",
|
||||
/* Warn ADISC status */
|
||||
lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS,
|
||||
"2755 ADISC DID:%06X Status:x%x/x%x\n",
|
||||
ndlp->nlp_DID, ulp_status,
|
||||
ulp_word4);
|
||||
lpfc_disc_state_machine(vport, ndlp, cmdiocb,
|
||||
|
@ -3045,9 +3041,9 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
* discovery. The PLOGI will retry.
|
||||
*/
|
||||
if (ulp_status) {
|
||||
/* LOGO failed */
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"2756 LOGO failure, No Retry DID:%06X "
|
||||
/* Warn LOGO status */
|
||||
lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS,
|
||||
"2756 LOGO, No Retry DID:%06X "
|
||||
"Status:x%x/x%x\n",
|
||||
ndlp->nlp_DID, ulp_status,
|
||||
ulp_word4);
|
||||
|
@ -4837,9 +4833,8 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
|
||||
(cmd == ELS_CMD_FDISC) &&
|
||||
(stat.un.b.lsRjtRsnCodeExp == LSEXP_OUT_OF_RESOURCE)){
|
||||
lpfc_printf_vlog(vport, KERN_ERR,
|
||||
LOG_TRACE_EVENT,
|
||||
"0125 FDISC Failed (x%x). "
|
||||
lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS,
|
||||
"0125 FDISC (x%x). "
|
||||
"Fabric out of resources\n",
|
||||
stat.un.lsRjtError);
|
||||
lpfc_vport_set_state(vport,
|
||||
|
@ -4877,9 +4872,8 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
LSEXP_NOTHING_MORE) {
|
||||
vport->fc_sparam.cmn.bbRcvSizeMsb &= 0xf;
|
||||
retry = 1;
|
||||
lpfc_printf_vlog(vport, KERN_ERR,
|
||||
LOG_TRACE_EVENT,
|
||||
"0820 FLOGI Failed (x%x). "
|
||||
lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS,
|
||||
"0820 FLOGI (x%x). "
|
||||
"BBCredit Not Supported\n",
|
||||
stat.un.lsRjtError);
|
||||
}
|
||||
|
@ -4891,9 +4885,8 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
((stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_PNAME) ||
|
||||
(stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_NPORT_ID))
|
||||
) {
|
||||
lpfc_printf_vlog(vport, KERN_ERR,
|
||||
LOG_TRACE_EVENT,
|
||||
"0122 FDISC Failed (x%x). "
|
||||
lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS,
|
||||
"0122 FDISC (x%x). "
|
||||
"Fabric Detected Bad WWN\n",
|
||||
stat.un.lsRjtError);
|
||||
lpfc_vport_set_state(vport,
|
||||
|
@ -5355,8 +5348,8 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
u32 ulp_status, ulp_word4, tmo, did, iotag;
|
||||
|
||||
if (!vport) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"3177 ELS response failed\n");
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
|
||||
"3177 null vport in ELS rsp\n");
|
||||
goto out;
|
||||
}
|
||||
if (cmdiocb->context_un.mbox)
|
||||
|
@ -9658,11 +9651,12 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
|
|||
if (piocb->cmd_flag & LPFC_DRIVER_ABORTED && !mbx_tmo_err)
|
||||
continue;
|
||||
|
||||
/* On the ELS ring we can have ELS_REQUESTs or
|
||||
* GEN_REQUESTs waiting for a response.
|
||||
/* On the ELS ring we can have ELS_REQUESTs, ELS_RSPs,
|
||||
* or GEN_REQUESTs waiting for a CQE response.
|
||||
*/
|
||||
ulp_command = get_job_cmnd(phba, piocb);
|
||||
if (ulp_command == CMD_ELS_REQUEST64_CR) {
|
||||
if (ulp_command == CMD_ELS_REQUEST64_WQE ||
|
||||
ulp_command == CMD_XMIT_ELS_RSP64_WQE) {
|
||||
list_add_tail(&piocb->dlist, &abort_list);
|
||||
|
||||
/* If the link is down when flushing ELS commands
|
||||
|
@ -11327,9 +11321,9 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
/* Check for retry */
|
||||
if (lpfc_els_retry(phba, cmdiocb, rspiocb))
|
||||
goto out;
|
||||
/* FDISC failed */
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"0126 FDISC failed. (x%x/x%x)\n",
|
||||
/* Warn FDISC status */
|
||||
lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS,
|
||||
"0126 FDISC cmpl status: x%x/x%x)\n",
|
||||
ulp_status, ulp_word4);
|
||||
goto fdisc_failed;
|
||||
}
|
||||
|
|
|
@ -527,6 +527,9 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
|
|||
* the following lpfc_nlp_put is necessary after fabric node is
|
||||
* recovered.
|
||||
*/
|
||||
spin_lock_irqsave(&ndlp->lock, iflags);
|
||||
ndlp->nlp_flag &= ~NLP_IN_DEV_LOSS;
|
||||
spin_unlock_irqrestore(&ndlp->lock, iflags);
|
||||
if (recovering) {
|
||||
lpfc_printf_vlog(vport, KERN_INFO,
|
||||
LOG_DISCOVERY | LOG_NODE,
|
||||
|
@ -539,6 +542,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
|
|||
spin_lock_irqsave(&ndlp->lock, iflags);
|
||||
ndlp->save_flags |= NLP_IN_RECOV_POST_DEV_LOSS;
|
||||
spin_unlock_irqrestore(&ndlp->lock, iflags);
|
||||
return fcf_inuse;
|
||||
} else if (ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
|
||||
/* Fabric node fully recovered before this dev_loss_tmo
|
||||
* queue work is processed. Thus, ignore the
|
||||
|
@ -552,15 +556,9 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
|
|||
ndlp->nlp_DID, kref_read(&ndlp->kref),
|
||||
ndlp, ndlp->nlp_flag,
|
||||
vport->port_state);
|
||||
spin_lock_irqsave(&ndlp->lock, iflags);
|
||||
ndlp->nlp_flag &= ~NLP_IN_DEV_LOSS;
|
||||
spin_unlock_irqrestore(&ndlp->lock, iflags);
|
||||
return fcf_inuse;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&ndlp->lock, iflags);
|
||||
ndlp->nlp_flag &= ~NLP_IN_DEV_LOSS;
|
||||
spin_unlock_irqrestore(&ndlp->lock, iflags);
|
||||
lpfc_nlp_put(ndlp);
|
||||
return fcf_inuse;
|
||||
}
|
||||
|
|
|
@ -561,6 +561,27 @@ struct fc_vft_header {
|
|||
|
||||
#include <uapi/scsi/fc/fc_els.h>
|
||||
|
||||
/*
|
||||
* Application Header
|
||||
*/
|
||||
struct fc_app_header {
|
||||
uint32_t dst_app_id;
|
||||
uint32_t src_app_id;
|
||||
#define LOOPBACK_SRC_APPID 0x4321
|
||||
uint32_t word2;
|
||||
uint32_t word3;
|
||||
};
|
||||
|
||||
/*
|
||||
* dfctl optional header definition
|
||||
*/
|
||||
enum lpfc_fc_dfctl {
|
||||
LPFC_FC_NO_DEVICE_HEADER,
|
||||
LPFC_FC_16B_DEVICE_HEADER,
|
||||
LPFC_FC_32B_DEVICE_HEADER,
|
||||
LPFC_FC_64B_DEVICE_HEADER,
|
||||
};
|
||||
|
||||
/*
|
||||
* Extended Link Service LS_COMMAND codes (Payload Word 0)
|
||||
*/
|
||||
|
|
|
@ -4847,6 +4847,7 @@ struct fcp_iwrite64_wqe {
|
|||
#define cmd_buff_len_SHIFT 16
|
||||
#define cmd_buff_len_MASK 0x00000ffff
|
||||
#define cmd_buff_len_WORD word3
|
||||
/* Note: payload_offset_len field depends on ASIC support */
|
||||
#define payload_offset_len_SHIFT 0
|
||||
#define payload_offset_len_MASK 0x0000ffff
|
||||
#define payload_offset_len_WORD word3
|
||||
|
@ -4863,6 +4864,7 @@ struct fcp_iread64_wqe {
|
|||
#define cmd_buff_len_SHIFT 16
|
||||
#define cmd_buff_len_MASK 0x00000ffff
|
||||
#define cmd_buff_len_WORD word3
|
||||
/* Note: payload_offset_len field depends on ASIC support */
|
||||
#define payload_offset_len_SHIFT 0
|
||||
#define payload_offset_len_MASK 0x0000ffff
|
||||
#define payload_offset_len_WORD word3
|
||||
|
@ -4879,6 +4881,7 @@ struct fcp_icmnd64_wqe {
|
|||
#define cmd_buff_len_SHIFT 16
|
||||
#define cmd_buff_len_MASK 0x00000ffff
|
||||
#define cmd_buff_len_WORD word3
|
||||
/* Note: payload_offset_len field depends on ASIC support */
|
||||
#define payload_offset_len_SHIFT 0
|
||||
#define payload_offset_len_MASK 0x0000ffff
|
||||
#define payload_offset_len_WORD word3
|
||||
|
|
|
@ -4699,6 +4699,7 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
|
|||
uint64_t wwn;
|
||||
bool use_no_reset_hba = false;
|
||||
int rc;
|
||||
u8 if_type;
|
||||
|
||||
if (lpfc_no_hba_reset_cnt) {
|
||||
if (phba->sli_rev < LPFC_SLI_REV4 &&
|
||||
|
@ -4773,10 +4774,24 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
|
|||
shost->max_id = LPFC_MAX_TARGET;
|
||||
shost->max_lun = vport->cfg_max_luns;
|
||||
shost->this_id = -1;
|
||||
if (phba->sli_rev == LPFC_SLI_REV4)
|
||||
|
||||
/* Set max_cmd_len applicable to ASIC support */
|
||||
if (phba->sli_rev == LPFC_SLI_REV4) {
|
||||
if_type = bf_get(lpfc_sli_intf_if_type,
|
||||
&phba->sli4_hba.sli_intf);
|
||||
switch (if_type) {
|
||||
case LPFC_SLI_INTF_IF_TYPE_2:
|
||||
fallthrough;
|
||||
case LPFC_SLI_INTF_IF_TYPE_6:
|
||||
shost->max_cmd_len = LPFC_FCP_CDB_LEN_32;
|
||||
else
|
||||
break;
|
||||
default:
|
||||
shost->max_cmd_len = LPFC_FCP_CDB_LEN;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
shost->max_cmd_len = LPFC_FCP_CDB_LEN;
|
||||
}
|
||||
|
||||
if (phba->sli_rev == LPFC_SLI_REV4) {
|
||||
if (!phba->cfg_fcp_mq_threshold ||
|
||||
|
@ -10436,6 +10451,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
|
|||
struct lpfc_vector_map_info *cpup;
|
||||
struct lpfc_vector_map_info *eqcpup;
|
||||
struct lpfc_eq_intr_info *eqi;
|
||||
u32 wqesize;
|
||||
|
||||
/*
|
||||
* Create HBA Record arrays.
|
||||
|
@ -10655,9 +10671,15 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
|
|||
* Create ELS Work Queues
|
||||
*/
|
||||
|
||||
/* Create slow-path ELS Work Queue */
|
||||
/*
|
||||
* Create slow-path ELS Work Queue.
|
||||
* Increase the ELS WQ size when WQEs contain an embedded cdb
|
||||
*/
|
||||
wqesize = (phba->fcp_embed_io) ?
|
||||
LPFC_WQE128_SIZE : phba->sli4_hba.wq_esize;
|
||||
|
||||
qdesc = lpfc_sli4_queue_alloc(phba, LPFC_DEFAULT_PAGE_SIZE,
|
||||
phba->sli4_hba.wq_esize,
|
||||
wqesize,
|
||||
phba->sli4_hba.wq_ecount, cpu);
|
||||
if (!qdesc) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
|
||||
|
|
|
@ -4760,7 +4760,7 @@ static int lpfc_scsi_prep_cmnd_buf_s4(struct lpfc_vport *vport,
|
|||
|
||||
/* Word 3 */
|
||||
bf_set(payload_offset_len, &wqe->fcp_icmd,
|
||||
sizeof(struct fcp_cmnd32) + sizeof(struct fcp_rsp));
|
||||
sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp));
|
||||
|
||||
/* Word 6 */
|
||||
bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com,
|
||||
|
|
|
@ -1940,12 +1940,15 @@ lpfc_issue_cmf_sync_wqe(struct lpfc_hba *phba, u32 ms, u64 total)
|
|||
atot = atomic_xchg(&phba->cgn_sync_alarm_cnt, 0);
|
||||
wtot = atomic_xchg(&phba->cgn_sync_warn_cnt, 0);
|
||||
|
||||
spin_lock_irqsave(&phba->hbalock, iflags);
|
||||
|
||||
/* ONLY Managed mode will send the CMF_SYNC_WQE to the HBA */
|
||||
if (phba->cmf_active_mode != LPFC_CFG_MANAGED ||
|
||||
phba->link_state == LPFC_LINK_DOWN)
|
||||
return 0;
|
||||
phba->link_state < LPFC_LINK_UP) {
|
||||
ret_val = 0;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&phba->hbalock, iflags);
|
||||
sync_buf = __lpfc_sli_get_iocbq(phba);
|
||||
if (!sync_buf) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT,
|
||||
|
@ -8818,7 +8821,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
|
|||
rc = lpfc_sli4_queue_setup(phba);
|
||||
if (unlikely(rc)) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"0381 Error %d during queue setup.\n ", rc);
|
||||
"0381 Error %d during queue setup.\n", rc);
|
||||
goto out_stop_timers;
|
||||
}
|
||||
/* Initialize the driver internal SLI layer lists. */
|
||||
|
@ -11090,9 +11093,17 @@ __lpfc_sli_prep_xmit_seq64_s4(struct lpfc_iocbq *cmdiocbq,
|
|||
/* Word 9 */
|
||||
bf_set(wqe_rcvoxid, &wqe->xmit_sequence.wqe_com, ox_id);
|
||||
|
||||
if (cmdiocbq->cmd_flag & (LPFC_IO_LIBDFC | LPFC_IO_LOOPBACK)) {
|
||||
/* Word 10 */
|
||||
if (cmdiocbq->cmd_flag & LPFC_IO_VMID) {
|
||||
bf_set(wqe_appid, &wqe->xmit_sequence.wqe_com, 1);
|
||||
bf_set(wqe_wqes, &wqe->xmit_sequence.wqe_com, 1);
|
||||
wqe->words[31] = LOOPBACK_SRC_APPID;
|
||||
}
|
||||
|
||||
/* Word 12 */
|
||||
if (cmdiocbq->cmd_flag & (LPFC_IO_LIBDFC | LPFC_IO_LOOPBACK))
|
||||
wqe->xmit_sequence.xmit_len = full_size;
|
||||
}
|
||||
else
|
||||
wqe->xmit_sequence.xmit_len =
|
||||
wqe->xmit_sequence.bde.tus.f.bdeSize;
|
||||
|
@ -18431,6 +18442,7 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
|
|||
{
|
||||
/* make rctl_names static to save stack space */
|
||||
struct fc_vft_header *fc_vft_hdr;
|
||||
struct fc_app_header *fc_app_hdr;
|
||||
uint32_t *header = (uint32_t *) fc_hdr;
|
||||
|
||||
#define FC_RCTL_MDS_DIAGS 0xF4
|
||||
|
@ -18486,6 +18498,32 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
|
|||
goto drop;
|
||||
}
|
||||
|
||||
if (unlikely(phba->link_flag == LS_LOOPBACK_MODE &&
|
||||
phba->cfg_vmid_app_header)) {
|
||||
/* Application header is 16B device header */
|
||||
if (fc_hdr->fh_df_ctl & LPFC_FC_16B_DEVICE_HEADER) {
|
||||
fc_app_hdr = (struct fc_app_header *) (fc_hdr + 1);
|
||||
if (be32_to_cpu(fc_app_hdr->src_app_id) !=
|
||||
LOOPBACK_SRC_APPID) {
|
||||
lpfc_printf_log(phba, KERN_WARNING,
|
||||
LOG_ELS | LOG_LIBDFC,
|
||||
"1932 Loopback src app id "
|
||||
"not matched, app_id:x%x\n",
|
||||
be32_to_cpu(fc_app_hdr->src_app_id));
|
||||
|
||||
goto drop;
|
||||
}
|
||||
} else {
|
||||
lpfc_printf_log(phba, KERN_WARNING,
|
||||
LOG_ELS | LOG_LIBDFC,
|
||||
"1933 Loopback df_ctl bit not set, "
|
||||
"df_ctl:x%x\n",
|
||||
fc_hdr->fh_df_ctl);
|
||||
|
||||
goto drop;
|
||||
}
|
||||
}
|
||||
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
|
||||
"2538 Received frame rctl:x%x, type:x%x, "
|
||||
"frame Data:%08x %08x %08x %08x %08x %08x %08x\n",
|
||||
|
@ -21149,7 +21187,7 @@ lpfc_drain_txq(struct lpfc_hba *phba)
|
|||
if (!piocbq) {
|
||||
spin_unlock_irqrestore(&pring->ring_lock, iflags);
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
|
||||
"2823 txq empty and txq_cnt is %d\n ",
|
||||
"2823 txq empty and txq_cnt is %d\n",
|
||||
txq_cnt);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
* included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
#define LPFC_DRIVER_VERSION "14.4.0.4"
|
||||
#define LPFC_DRIVER_VERSION "14.4.0.5"
|
||||
#define LPFC_DRIVER_NAME "lpfc"
|
||||
|
||||
/* Used for SLI 2/3 */
|
||||
|
|
|
@ -626,6 +626,7 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
|
|||
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
int rc;
|
||||
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq);
|
||||
|
||||
if (vport->port_type == LPFC_PHYSICAL_PORT) {
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
|
||||
|
@ -679,21 +680,49 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
|
|||
if (!ndlp)
|
||||
goto skip_logo;
|
||||
|
||||
/* Send the DA_ID and Fabric LOGO to cleanup the NPIV fabric entries. */
|
||||
if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE &&
|
||||
phba->link_state >= LPFC_LINK_UP &&
|
||||
phba->fc_topology != LPFC_TOPOLOGY_LOOP) {
|
||||
if (vport->cfg_enable_da_id) {
|
||||
/* Send DA_ID and wait for a completion. */
|
||||
/* Send DA_ID and wait for a completion. This is best
|
||||
* effort. If the DA_ID fails, likely the fabric will
|
||||
* "leak" NportIDs but at least the driver issued the
|
||||
* command.
|
||||
*/
|
||||
ndlp = lpfc_findnode_did(vport, NameServer_DID);
|
||||
if (!ndlp)
|
||||
goto issue_logo;
|
||||
|
||||
spin_lock_irq(&ndlp->lock);
|
||||
ndlp->da_id_waitq = &waitq;
|
||||
ndlp->save_flags |= NLP_WAIT_FOR_DA_ID;
|
||||
spin_unlock_irq(&ndlp->lock);
|
||||
|
||||
rc = lpfc_ns_cmd(vport, SLI_CTNS_DA_ID, 0, 0);
|
||||
if (rc) {
|
||||
lpfc_printf_log(vport->phba, KERN_WARNING,
|
||||
LOG_VPORT,
|
||||
"1829 CT command failed to "
|
||||
"delete objects on fabric, "
|
||||
"rc %d\n", rc);
|
||||
}
|
||||
if (!rc) {
|
||||
wait_event_timeout(waitq,
|
||||
!(ndlp->save_flags & NLP_WAIT_FOR_DA_ID),
|
||||
msecs_to_jiffies(phba->fc_ratov * 2000));
|
||||
}
|
||||
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_VPORT | LOG_ELS,
|
||||
"1829 DA_ID issue status %d. "
|
||||
"SFlag x%x NState x%x, NFlag x%x "
|
||||
"Rpi x%x\n",
|
||||
rc, ndlp->save_flags, ndlp->nlp_state,
|
||||
ndlp->nlp_flag, ndlp->nlp_rpi);
|
||||
|
||||
/* Remove the waitq and save_flags. It no
|
||||
* longer matters if the wake happened.
|
||||
*/
|
||||
spin_lock_irq(&ndlp->lock);
|
||||
ndlp->da_id_waitq = NULL;
|
||||
ndlp->save_flags &= ~NLP_WAIT_FOR_DA_ID;
|
||||
spin_unlock_irq(&ndlp->lock);
|
||||
}
|
||||
|
||||
issue_logo:
|
||||
/*
|
||||
* If the vpi is not registered, then a valid FDISC doesn't
|
||||
* exist and there is no need for a ELS LOGO. Just cleanup
|
||||
|
|
|
@ -6380,7 +6380,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
|
|||
GFP_KERNEL);
|
||||
if (!fusion->stream_detect_by_ld[i]) {
|
||||
dev_err(&instance->pdev->dev,
|
||||
"unable to allocate stream detect by LD\n ");
|
||||
"unable to allocate stream detect by LD\n");
|
||||
for (j = 0; j < i; ++j)
|
||||
kfree(fusion->stream_detect_by_ld[j]);
|
||||
kfree(fusion->stream_detect_by_ld);
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
#define MPI3_SECURITY_PGAD_SLOT_GROUP_MASK (0x0000ff00)
|
||||
#define MPI3_SECURITY_PGAD_SLOT_GROUP_SHIFT (8)
|
||||
#define MPI3_SECURITY_PGAD_SLOT_MASK (0x000000ff)
|
||||
#define MPI3_INSTANCE_PGAD_INSTANCE_MASK (0x0000ffff)
|
||||
struct mpi3_config_request {
|
||||
__le16 host_tag;
|
||||
u8 ioc_use_only02;
|
||||
|
@ -75,7 +76,8 @@ struct mpi3_config_request {
|
|||
u8 ioc_use_only06;
|
||||
u8 msg_flags;
|
||||
__le16 change_count;
|
||||
__le16 reserved0a;
|
||||
u8 proxy_ioc_number;
|
||||
u8 reserved0b;
|
||||
u8 page_version;
|
||||
u8 page_number;
|
||||
u8 page_type;
|
||||
|
@ -206,6 +208,9 @@ struct mpi3_config_page_header {
|
|||
#define MPI3_MFGPAGE_DEVID_SAS5116_MPI_MGMT (0x00b5)
|
||||
#define MPI3_MFGPAGE_DEVID_SAS5116_NVME_MGMT (0x00b6)
|
||||
#define MPI3_MFGPAGE_DEVID_SAS5116_PCIE_SWITCH (0x00b8)
|
||||
#define MPI3_MFGPAGE_DEVID_SAS5248_MPI (0x00f0)
|
||||
#define MPI3_MFGPAGE_DEVID_SAS5248_MPI_NS (0x00f1)
|
||||
#define MPI3_MFGPAGE_DEVID_SAS5248_PCIE_SWITCH (0x00f2)
|
||||
struct mpi3_man_page0 {
|
||||
struct mpi3_config_page_header header;
|
||||
u8 chip_revision[8];
|
||||
|
@ -1074,6 +1079,8 @@ struct mpi3_io_unit_page8 {
|
|||
#define MPI3_IOUNIT8_SBSTATE_SVN_UPDATE_PENDING (0x04)
|
||||
#define MPI3_IOUNIT8_SBSTATE_KEY_UPDATE_PENDING (0x02)
|
||||
#define MPI3_IOUNIT8_SBSTATE_SECURE_BOOT_ENABLED (0x01)
|
||||
#define MPI3_IOUNIT8_SBMODE_CURRENT_KEY_IOUNIT17 (0x10)
|
||||
#define MPI3_IOUNIT8_SBMODE_HARD_SECURE_RECERTIFIED (0x08)
|
||||
struct mpi3_io_unit_page9 {
|
||||
struct mpi3_config_page_header header;
|
||||
__le32 flags;
|
||||
|
@ -1089,6 +1096,8 @@ struct mpi3_io_unit_page9 {
|
|||
#define MPI3_IOUNIT9_FLAGS_UBM_ENCLOSURE_ORDER_BACKPLANE_TYPE (0x00000004)
|
||||
#define MPI3_IOUNIT9_FLAGS_VDFIRST_ENABLED (0x00000001)
|
||||
#define MPI3_IOUNIT9_FIRSTDEVICE_UNKNOWN (0xffff)
|
||||
#define MPI3_IOUNIT9_FIRSTDEVICE_IN_DRIVER_PAGE_0 (0xfffe)
|
||||
|
||||
struct mpi3_io_unit_page10 {
|
||||
struct mpi3_config_page_header header;
|
||||
u8 flags;
|
||||
|
@ -1224,6 +1233,19 @@ struct mpi3_io_unit_page15 {
|
|||
#define MPI3_IOUNIT15_FLAGS_EPRSUPPORT_WITHOUT_POWER_BRAKE_GPIO (0x01)
|
||||
#define MPI3_IOUNIT15_FLAGS_EPRSUPPORT_WITH_POWER_BRAKE_GPIO (0x02)
|
||||
#define MPI3_IOUNIT15_NUMPOWERBUDGETDATA_POWER_BUDGETING_DISABLED (0x00)
|
||||
|
||||
struct mpi3_io_unit_page17 {
|
||||
struct mpi3_config_page_header header;
|
||||
u8 num_instances;
|
||||
u8 instance;
|
||||
__le16 reserved0a;
|
||||
__le32 reserved0c[4];
|
||||
__le16 key_length;
|
||||
u8 encryption_algorithm;
|
||||
u8 reserved1f;
|
||||
__le32 current_key[];
|
||||
};
|
||||
#define MPI3_IOUNIT17_PAGEVERSION (0x00)
|
||||
struct mpi3_ioc_page0 {
|
||||
struct mpi3_config_page_header header;
|
||||
__le32 reserved08;
|
||||
|
@ -1311,7 +1333,7 @@ struct mpi3_driver_page0 {
|
|||
u8 tur_interval;
|
||||
u8 reserved10;
|
||||
u8 security_key_timeout;
|
||||
__le16 reserved12;
|
||||
__le16 first_device;
|
||||
__le32 reserved14;
|
||||
__le32 reserved18;
|
||||
};
|
||||
|
@ -1324,10 +1346,13 @@ struct mpi3_driver_page0 {
|
|||
#define MPI3_DRIVER0_BSDOPTS_REGISTRATION_IOC_AND_DEVS (0x00000000)
|
||||
#define MPI3_DRIVER0_BSDOPTS_REGISTRATION_IOC_ONLY (0x00000001)
|
||||
#define MPI3_DRIVER0_BSDOPTS_REGISTRATION_IOC_AND_INTERNAL_DEVS (0x00000002)
|
||||
#define MPI3_DRIVER0_FIRSTDEVICE_IGNORE1 (0x0000)
|
||||
#define MPI3_DRIVER0_FIRSTDEVICE_IGNORE2 (0xffff)
|
||||
struct mpi3_driver_page1 {
|
||||
struct mpi3_config_page_header header;
|
||||
__le32 flags;
|
||||
__le32 reserved0c;
|
||||
u8 time_stamp_update;
|
||||
u8 reserved0d[3];
|
||||
__le16 host_diag_trace_max_size;
|
||||
__le16 host_diag_trace_min_size;
|
||||
__le16 host_diag_trace_decrement_size;
|
||||
|
@ -2347,6 +2372,10 @@ struct mpi3_device0_vd_format {
|
|||
#define MPI3_DEVICE0_VD_DEVICE_INFO_SAS (0x0001)
|
||||
#define MPI3_DEVICE0_VD_FLAGS_IO_THROTTLE_GROUP_QD_MASK (0xf000)
|
||||
#define MPI3_DEVICE0_VD_FLAGS_IO_THROTTLE_GROUP_QD_SHIFT (12)
|
||||
#define MPI3_DEVICE0_VD_FLAGS_OSEXPOSURE_MASK (0x0003)
|
||||
#define MPI3_DEVICE0_VD_FLAGS_OSEXPOSURE_HDD (0x0000)
|
||||
#define MPI3_DEVICE0_VD_FLAGS_OSEXPOSURE_SSD (0x0001)
|
||||
#define MPI3_DEVICE0_VD_FLAGS_OSEXPOSURE_NO_GUIDANCE (0x0002)
|
||||
union mpi3_device0_dev_spec_format {
|
||||
struct mpi3_device0_sas_sata_format sas_sata_format;
|
||||
struct mpi3_device0_pcie_format pcie_format;
|
||||
|
|
|
@ -205,13 +205,14 @@ struct mpi3_encrypted_hash_entry {
|
|||
u8 hash_image_type;
|
||||
u8 hash_algorithm;
|
||||
u8 encryption_algorithm;
|
||||
u8 reserved03;
|
||||
u8 flags;
|
||||
__le16 public_key_size;
|
||||
__le16 signature_size;
|
||||
__le32 public_key[MPI3_PUBLIC_KEY_MAX];
|
||||
};
|
||||
|
||||
#define MPI3_HASH_IMAGE_TYPE_KEY_WITH_SIGNATURE (0x03)
|
||||
#define MPI3_HASH_IMAGE_TYPE_KEY_WITH_HASH (0x03)
|
||||
#define MPI3_HASH_IMAGE_TYPE_KEY_WITH_HASH_1_OF_2 (0x04)
|
||||
#define MPI3_HASH_IMAGE_TYPE_KEY_WITH_HASH_2_OF_2 (0x05)
|
||||
#define MPI3_HASH_ALGORITHM_VERSION_MASK (0xe0)
|
||||
#define MPI3_HASH_ALGORITHM_VERSION_NONE (0x00)
|
||||
#define MPI3_HASH_ALGORITHM_VERSION_SHA1 (0x20)
|
||||
|
@ -230,6 +231,12 @@ struct mpi3_encrypted_hash_entry {
|
|||
#define MPI3_ENCRYPTION_ALGORITHM_RSA4096 (0x05)
|
||||
#define MPI3_ENCRYPTION_ALGORITHM_RSA3072 (0x06)
|
||||
|
||||
/* hierarchical signature system (hss) */
|
||||
#define MPI3_ENCRYPTION_ALGORITHM_ML_DSA_87 (0x0b)
|
||||
#define MPI3_ENCRYPTION_ALGORITHM_ML_DSA_65 (0x0c)
|
||||
#define MPI3_ENCRYPTION_ALGORITHM_ML_DSA_44 (0x0d)
|
||||
#define MPI3_ENCRYPTED_HASH_ENTRY_FLAGS_PAIRED_KEY_MASK (0x0f)
|
||||
|
||||
#ifndef MPI3_ENCRYPTED_HASH_ENTRY_MAX
|
||||
#define MPI3_ENCRYPTED_HASH_ENTRY_MAX (1)
|
||||
#endif
|
||||
|
|
|
@ -39,6 +39,12 @@ struct mpi3_ioc_init_request {
|
|||
#define MPI3_WHOINIT_HOST_DRIVER (0x03)
|
||||
#define MPI3_WHOINIT_MANUFACTURER (0x04)
|
||||
|
||||
#define MPI3_IOCINIT_DRIVERCAP_OSEXPOSURE_MASK (0x00000003)
|
||||
#define MPI3_IOCINIT_DRIVERCAP_OSEXPOSURE_NO_GUIDANCE (0x00000000)
|
||||
#define MPI3_IOCINIT_DRIVERCAP_OSEXPOSURE_NO_SPECIAL (0x00000001)
|
||||
#define MPI3_IOCINIT_DRIVERCAP_OSEXPOSURE_REPORT_AS_HDD (0x00000002)
|
||||
#define MPI3_IOCINIT_DRIVERCAP_OSEXPOSURE_REPORT_AS_SSD (0x00000003)
|
||||
|
||||
struct mpi3_ioc_facts_request {
|
||||
__le16 host_tag;
|
||||
u8 ioc_use_only02;
|
||||
|
@ -140,6 +146,8 @@ struct mpi3_ioc_facts_data {
|
|||
#define MPI3_IOCFACTS_EXCEPT_MANUFACT_CHECKSUM_FAIL (0x0020)
|
||||
#define MPI3_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0010)
|
||||
#define MPI3_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL (0x0008)
|
||||
#define MPI3_IOCFACTS_EXCEPT_BLOCKING_BOOT_EVENT (0x0004)
|
||||
#define MPI3_IOCFACTS_EXCEPT_SECURITY_SELFTEST_FAILURE (0x0002)
|
||||
#define MPI3_IOCFACTS_EXCEPT_BOOTSTAT_MASK (0x0001)
|
||||
#define MPI3_IOCFACTS_EXCEPT_BOOTSTAT_PRIMARY (0x0000)
|
||||
#define MPI3_IOCFACTS_EXCEPT_BOOTSTAT_SECONDARY (0x0001)
|
||||
|
|
|
@ -18,7 +18,7 @@ union mpi3_version_union {
|
|||
|
||||
#define MPI3_VERSION_MAJOR (3)
|
||||
#define MPI3_VERSION_MINOR (0)
|
||||
#define MPI3_VERSION_UNIT (31)
|
||||
#define MPI3_VERSION_UNIT (34)
|
||||
#define MPI3_VERSION_DEV (0)
|
||||
#define MPI3_DEVHANDLE_INVALID (0xffff)
|
||||
struct mpi3_sysif_oper_queue_indexes {
|
||||
|
@ -158,6 +158,7 @@ struct mpi3_sysif_registers {
|
|||
#define MPI3_SYSIF_FAULT_CODE_SOFT_RESET_NEEDED (0x0000f004)
|
||||
#define MPI3_SYSIF_FAULT_CODE_POWER_CYCLE_REQUIRED (0x0000f005)
|
||||
#define MPI3_SYSIF_FAULT_CODE_TEMP_THRESHOLD_EXCEEDED (0x0000f006)
|
||||
#define MPI3_SYSIF_FAULT_CODE_INSUFFICIENT_PCI_SLOT_POWER (0x0000f007)
|
||||
#define MPI3_SYSIF_FAULT_INFO0_OFFSET (0x00001c14)
|
||||
#define MPI3_SYSIF_FAULT_INFO1_OFFSET (0x00001c18)
|
||||
#define MPI3_SYSIF_FAULT_INFO2_OFFSET (0x00001c1c)
|
||||
|
@ -410,6 +411,7 @@ struct mpi3_default_reply {
|
|||
#define MPI3_IOCSTATUS_INSUFFICIENT_RESOURCES (0x0006)
|
||||
#define MPI3_IOCSTATUS_INVALID_FIELD (0x0007)
|
||||
#define MPI3_IOCSTATUS_INVALID_STATE (0x0008)
|
||||
#define MPI3_IOCSTATUS_SHUTDOWN_ACTIVE (0x0009)
|
||||
#define MPI3_IOCSTATUS_INSUFFICIENT_POWER (0x000a)
|
||||
#define MPI3_IOCSTATUS_INVALID_CHANGE_COUNT (0x000b)
|
||||
#define MPI3_IOCSTATUS_ALLOWED_CMD_BLOCK (0x000c)
|
||||
|
|
|
@ -57,8 +57,8 @@ extern struct list_head mrioc_list;
|
|||
extern int prot_mask;
|
||||
extern atomic64_t event_counter;
|
||||
|
||||
#define MPI3MR_DRIVER_VERSION "8.10.0.5.50"
|
||||
#define MPI3MR_DRIVER_RELDATE "08-Aug-2024"
|
||||
#define MPI3MR_DRIVER_VERSION "8.12.0.0.50"
|
||||
#define MPI3MR_DRIVER_RELDATE "05-Sept-2024"
|
||||
|
||||
#define MPI3MR_DRIVER_NAME "mpi3mr"
|
||||
#define MPI3MR_DRIVER_LICENSE "GPL"
|
||||
|
@ -178,7 +178,7 @@ extern atomic64_t event_counter;
|
|||
#define MPI3MR_DEFAULT_SDEV_QD 32
|
||||
|
||||
/* Definitions for Threaded IRQ poll*/
|
||||
#define MPI3MR_IRQ_POLL_SLEEP 2
|
||||
#define MPI3MR_IRQ_POLL_SLEEP 20
|
||||
#define MPI3MR_IRQ_POLL_TRIGGER_IOCOUNT 8
|
||||
|
||||
/* Definitions for the controller security status*/
|
||||
|
@ -1090,6 +1090,7 @@ struct scmd_priv {
|
|||
* @evtack_cmds_bitmap: Event Ack bitmap
|
||||
* @delayed_evtack_cmds_list: Delayed event acknowledgment list
|
||||
* @ts_update_counter: Timestamp update counter
|
||||
* @ts_update_interval: Timestamp update interval
|
||||
* @reset_in_progress: Reset in progress flag
|
||||
* @unrecoverable: Controller unrecoverable flag
|
||||
* @prev_reset_result: Result of previous reset
|
||||
|
@ -1277,7 +1278,8 @@ struct mpi3mr_ioc {
|
|||
unsigned long *evtack_cmds_bitmap;
|
||||
struct list_head delayed_evtack_cmds_list;
|
||||
|
||||
u32 ts_update_counter;
|
||||
u16 ts_update_counter;
|
||||
u16 ts_update_interval;
|
||||
u8 reset_in_progress;
|
||||
u8 unrecoverable;
|
||||
int prev_reset_result;
|
||||
|
|
|
@ -728,7 +728,7 @@ static irqreturn_t mpi3mr_isr_poll(int irq, void *privdata)
|
|||
mpi3mr_process_op_reply_q(mrioc,
|
||||
intr_info->op_reply_q);
|
||||
|
||||
usleep_range(MPI3MR_IRQ_POLL_SLEEP, 10 * MPI3MR_IRQ_POLL_SLEEP);
|
||||
usleep_range(MPI3MR_IRQ_POLL_SLEEP, MPI3MR_IRQ_POLL_SLEEP + 1);
|
||||
|
||||
} while (atomic_read(&intr_info->op_reply_q->pend_ios) &&
|
||||
(num_op_reply < mrioc->max_host_ios));
|
||||
|
@ -1362,6 +1362,10 @@ static int mpi3mr_bring_ioc_ready(struct mpi3mr_ioc *mrioc)
|
|||
int retval = 0;
|
||||
enum mpi3mr_iocstate ioc_state;
|
||||
u64 base_info;
|
||||
u8 retry = 0;
|
||||
u64 start_time, elapsed_time_sec;
|
||||
|
||||
retry_bring_ioc_ready:
|
||||
|
||||
ioc_status = readl(&mrioc->sysif_regs->ioc_status);
|
||||
ioc_config = readl(&mrioc->sysif_regs->ioc_configuration);
|
||||
|
@ -1380,26 +1384,23 @@ static int mpi3mr_bring_ioc_ready(struct mpi3mr_ioc *mrioc)
|
|||
ioc_info(mrioc, "controller is in %s state during detection\n",
|
||||
mpi3mr_iocstate_name(ioc_state));
|
||||
|
||||
if (ioc_state == MRIOC_STATE_BECOMING_READY ||
|
||||
ioc_state == MRIOC_STATE_RESET_REQUESTED) {
|
||||
timeout = mrioc->ready_timeout * 10;
|
||||
|
||||
do {
|
||||
msleep(100);
|
||||
} while (--timeout);
|
||||
ioc_state = mpi3mr_get_iocstate(mrioc);
|
||||
|
||||
if (ioc_state != MRIOC_STATE_BECOMING_READY &&
|
||||
ioc_state != MRIOC_STATE_RESET_REQUESTED)
|
||||
break;
|
||||
|
||||
if (!pci_device_is_present(mrioc->pdev)) {
|
||||
mrioc->unrecoverable = 1;
|
||||
ioc_err(mrioc,
|
||||
"controller is not present while waiting to reset\n");
|
||||
retval = -1;
|
||||
ioc_err(mrioc, "controller is not present while waiting to reset\n");
|
||||
goto out_device_not_present;
|
||||
}
|
||||
|
||||
ioc_state = mpi3mr_get_iocstate(mrioc);
|
||||
ioc_info(mrioc,
|
||||
"controller is in %s state after waiting to reset\n",
|
||||
mpi3mr_iocstate_name(ioc_state));
|
||||
}
|
||||
msleep(100);
|
||||
} while (--timeout);
|
||||
|
||||
if (ioc_state == MRIOC_STATE_READY) {
|
||||
ioc_info(mrioc, "issuing message unit reset (MUR) to bring to reset state\n");
|
||||
|
@ -1460,6 +1461,9 @@ static int mpi3mr_bring_ioc_ready(struct mpi3mr_ioc *mrioc)
|
|||
ioc_config |= MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC;
|
||||
writel(ioc_config, &mrioc->sysif_regs->ioc_configuration);
|
||||
|
||||
if (retry == 0)
|
||||
start_time = jiffies;
|
||||
|
||||
timeout = mrioc->ready_timeout * 10;
|
||||
do {
|
||||
ioc_state = mpi3mr_get_iocstate(mrioc);
|
||||
|
@ -1469,6 +1473,12 @@ static int mpi3mr_bring_ioc_ready(struct mpi3mr_ioc *mrioc)
|
|||
mpi3mr_iocstate_name(ioc_state));
|
||||
return 0;
|
||||
}
|
||||
ioc_status = readl(&mrioc->sysif_regs->ioc_status);
|
||||
if ((ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) ||
|
||||
(ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT)) {
|
||||
mpi3mr_print_fault_info(mrioc);
|
||||
goto out_failed;
|
||||
}
|
||||
if (!pci_device_is_present(mrioc->pdev)) {
|
||||
mrioc->unrecoverable = 1;
|
||||
ioc_err(mrioc,
|
||||
|
@ -1477,9 +1487,19 @@ static int mpi3mr_bring_ioc_ready(struct mpi3mr_ioc *mrioc)
|
|||
goto out_device_not_present;
|
||||
}
|
||||
msleep(100);
|
||||
} while (--timeout);
|
||||
elapsed_time_sec = jiffies_to_msecs(jiffies - start_time)/1000;
|
||||
} while (elapsed_time_sec < mrioc->ready_timeout);
|
||||
|
||||
out_failed:
|
||||
elapsed_time_sec = jiffies_to_msecs(jiffies - start_time)/1000;
|
||||
if ((retry < 2) && (elapsed_time_sec < (mrioc->ready_timeout - 60))) {
|
||||
retry++;
|
||||
|
||||
ioc_warn(mrioc, "retrying to bring IOC ready, retry_count:%d\n"
|
||||
" elapsed time =%llu\n", retry, elapsed_time_sec);
|
||||
|
||||
goto retry_bring_ioc_ready;
|
||||
}
|
||||
ioc_state = mpi3mr_get_iocstate(mrioc);
|
||||
ioc_err(mrioc,
|
||||
"failed to bring to ready state, current state: %s\n",
|
||||
|
@ -2671,7 +2691,7 @@ static void mpi3mr_watchdog_work(struct work_struct *work)
|
|||
return;
|
||||
}
|
||||
|
||||
if (mrioc->ts_update_counter++ >= MPI3MR_TSUPDATE_INTERVAL) {
|
||||
if (mrioc->ts_update_counter++ >= mrioc->ts_update_interval) {
|
||||
mrioc->ts_update_counter = 0;
|
||||
mpi3mr_sync_timestamp(mrioc);
|
||||
}
|
||||
|
@ -3844,6 +3864,29 @@ static int mpi3mr_repost_diag_bufs(struct mpi3mr_ioc *mrioc)
|
|||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_read_tsu_interval - Update time stamp interval
|
||||
* @mrioc: Adapter instance reference
|
||||
*
|
||||
* Update time stamp interval if its defined in driver page 1,
|
||||
* otherwise use default value.
|
||||
*
|
||||
* Return: Nothing
|
||||
*/
|
||||
static void
|
||||
mpi3mr_read_tsu_interval(struct mpi3mr_ioc *mrioc)
|
||||
{
|
||||
struct mpi3_driver_page1 driver_pg1;
|
||||
u16 pg_sz = sizeof(driver_pg1);
|
||||
int retval = 0;
|
||||
|
||||
mrioc->ts_update_interval = MPI3MR_TSUPDATE_INTERVAL;
|
||||
|
||||
retval = mpi3mr_cfg_get_driver_pg1(mrioc, &driver_pg1, pg_sz);
|
||||
if (!retval && driver_pg1.time_stamp_update)
|
||||
mrioc->ts_update_interval = (driver_pg1.time_stamp_update * 60);
|
||||
}
|
||||
|
||||
/**
|
||||
* mpi3mr_print_ioc_info - Display controller information
|
||||
* @mrioc: Adapter instance reference
|
||||
|
@ -4140,6 +4183,7 @@ int mpi3mr_init_ioc(struct mpi3mr_ioc *mrioc)
|
|||
goto out_failed_noretry;
|
||||
}
|
||||
|
||||
mpi3mr_read_tsu_interval(mrioc);
|
||||
mpi3mr_print_ioc_info(mrioc);
|
||||
|
||||
if (!mrioc->cfg_page) {
|
||||
|
@ -4321,6 +4365,7 @@ int mpi3mr_reinit_ioc(struct mpi3mr_ioc *mrioc, u8 is_resume)
|
|||
goto out_failed_noretry;
|
||||
}
|
||||
|
||||
mpi3mr_read_tsu_interval(mrioc);
|
||||
mpi3mr_print_ioc_info(mrioc);
|
||||
|
||||
if (is_resume) {
|
||||
|
|
|
@ -8898,9 +8898,8 @@ _base_check_ioc_facts_changes(struct MPT3SAS_ADAPTER *ioc)
|
|||
ioc->device_remove_in_progress, pd_handles_sz, GFP_KERNEL);
|
||||
if (!device_remove_in_progress) {
|
||||
ioc_info(ioc,
|
||||
"Unable to allocate the memory for "
|
||||
"device_remove_in_progress of sz: %d\n "
|
||||
, pd_handles_sz);
|
||||
"Unable to allocate the memory for device_remove_in_progress of sz: %d\n",
|
||||
pd_handles_sz);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(device_remove_in_progress +
|
||||
|
|
|
@ -100,10 +100,12 @@ static void pm8001_map_queues(struct Scsi_Host *shost)
|
|||
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
|
||||
struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT];
|
||||
|
||||
if (pm8001_ha->number_of_intr > 1)
|
||||
if (pm8001_ha->number_of_intr > 1) {
|
||||
blk_mq_pci_map_queues(qmap, pm8001_ha->pdev, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
return blk_mq_map_queues(qmap);
|
||||
blk_mq_map_queues(qmap);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -2037,7 +2037,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
|
|||
atomic_dec(&pm8001_dev->running_req);
|
||||
break;
|
||||
}
|
||||
pm8001_dbg(pm8001_ha, IO, "scsi_status = 0x%x\n ",
|
||||
pm8001_dbg(pm8001_ha, IO, "scsi_status = 0x%x\n",
|
||||
psspPayload->ssp_resp_iu.status);
|
||||
spin_lock_irqsave(&t->task_state_lock, flags);
|
||||
t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
|
||||
|
|
|
@ -1946,7 +1946,7 @@ static void pmcraid_soft_reset(struct pmcraid_cmd *cmd)
|
|||
}
|
||||
|
||||
iowrite32(doorbell, pinstance->int_regs.host_ioa_interrupt_reg);
|
||||
ioread32(pinstance->int_regs.host_ioa_interrupt_reg),
|
||||
ioread32(pinstance->int_regs.host_ioa_interrupt_reg);
|
||||
int_reg = ioread32(pinstance->int_regs.ioa_host_interrupt_reg);
|
||||
|
||||
pmcraid_info("Waiting for IOA to become operational %x:%x\n",
|
||||
|
|
|
@ -310,7 +310,7 @@ struct qedf_ioreq *qedf_alloc_cmd(struct qedf_rport *fcport, u8 cmd_type)
|
|||
|
||||
if (!free_sqes) {
|
||||
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_IO,
|
||||
"Returning NULL, free_sqes=%d.\n ",
|
||||
"Returning NULL, free_sqes=%d.\n",
|
||||
free_sqes);
|
||||
goto out_failed;
|
||||
}
|
||||
|
|
|
@ -2760,7 +2760,6 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
|
|||
else
|
||||
bd_len = 0;
|
||||
alloc_len = msense_6 ? cmd[4] : get_unaligned_be16(cmd + 7);
|
||||
memset(arr, 0, SDEBUG_MAX_MSENSE_SZ);
|
||||
if (0x3 == pcontrol) { /* Saving values not supported */
|
||||
mk_sense_buffer(scp, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP, 0);
|
||||
return check_condition_result;
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#include <linux/fs.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/bio-integrity.h>
|
||||
#include <linux/hdreg.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/idr.h>
|
||||
|
@ -3404,7 +3403,7 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp,
|
|||
rcu_read_lock();
|
||||
vpd = rcu_dereference(sdkp->device->vpd_pgb1);
|
||||
|
||||
if (!vpd || vpd->len < 8) {
|
||||
if (!vpd || vpd->len <= 8) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
@ -4093,9 +4092,38 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
|
|||
{
|
||||
unsigned char cmd[6] = { START_STOP }; /* START_VALID */
|
||||
struct scsi_sense_hdr sshdr;
|
||||
struct scsi_failure failure_defs[] = {
|
||||
{
|
||||
/* Power on, reset, or bus device reset occurred */
|
||||
.sense = UNIT_ATTENTION,
|
||||
.asc = 0x29,
|
||||
.ascq = 0,
|
||||
.result = SAM_STAT_CHECK_CONDITION,
|
||||
},
|
||||
{
|
||||
/* Power on occurred */
|
||||
.sense = UNIT_ATTENTION,
|
||||
.asc = 0x29,
|
||||
.ascq = 1,
|
||||
.result = SAM_STAT_CHECK_CONDITION,
|
||||
},
|
||||
{
|
||||
/* SCSI bus reset */
|
||||
.sense = UNIT_ATTENTION,
|
||||
.asc = 0x29,
|
||||
.ascq = 2,
|
||||
.result = SAM_STAT_CHECK_CONDITION,
|
||||
},
|
||||
{}
|
||||
};
|
||||
struct scsi_failures failures = {
|
||||
.total_allowed = 3,
|
||||
.failure_definitions = failure_defs,
|
||||
};
|
||||
const struct scsi_exec_args exec_args = {
|
||||
.sshdr = &sshdr,
|
||||
.req_flags = BLK_MQ_REQ_PM,
|
||||
.failures = &failures,
|
||||
};
|
||||
struct scsi_device *sdp = sdkp->device;
|
||||
int res;
|
||||
|
|
|
@ -834,6 +834,9 @@ static int flush_buffer(struct scsi_tape *STp, int seek_next)
|
|||
int backspace, result;
|
||||
struct st_partstat *STps;
|
||||
|
||||
if (STp->ready != ST_READY)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If there was a bus reset, block further access
|
||||
* to this device.
|
||||
|
@ -841,8 +844,6 @@ static int flush_buffer(struct scsi_tape *STp, int seek_next)
|
|||
if (STp->pos_unknown)
|
||||
return (-EIO);
|
||||
|
||||
if (STp->ready != ST_READY)
|
||||
return 0;
|
||||
STps = &(STp->ps[STp->partition]);
|
||||
if (STps->rw == ST_WRITING) /* Writing */
|
||||
return st_flush_write_buffer(STp);
|
||||
|
|
|
@ -139,7 +139,7 @@ zalon_probe(struct parisc_device *dev)
|
|||
return -ENODEV;
|
||||
|
||||
if (request_irq(dev->irq, ncr53c8xx_intr, IRQF_SHARED, "zalon", host)) {
|
||||
dev_printk(KERN_ERR, &dev->dev, "irq problem with %d, detaching\n ",
|
||||
dev_printk(KERN_ERR, &dev->dev, "irq problem with %d, detaching\n",
|
||||
dev->irq);
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ static const struct __ufs_qcom_bw_table {
|
|||
[MODE_HS_RB][UFS_HS_G3][UFS_LANE_2] = { 1492582, 204800 },
|
||||
[MODE_HS_RB][UFS_HS_G4][UFS_LANE_2] = { 2915200, 409600 },
|
||||
[MODE_HS_RB][UFS_HS_G5][UFS_LANE_2] = { 5836800, 819200 },
|
||||
[MODE_MAX][0][0] = { 7643136, 307200 },
|
||||
[MODE_MAX][0][0] = { 7643136, 819200 },
|
||||
};
|
||||
|
||||
static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host);
|
||||
|
|
|
@ -501,7 +501,7 @@ static int check_extent_checksum(struct btree_trans *trans,
|
|||
prt_printf(&buf, "\n %s ", bch2_btree_id_str(o_btree));
|
||||
bch2_bkey_val_to_text(&buf, c, extent2);
|
||||
|
||||
struct nonce nonce = extent_nonce(extent.k->version, p.crc);
|
||||
struct nonce nonce = extent_nonce(extent.k->bversion, p.crc);
|
||||
struct bch_csum csum = bch2_checksum(c, p.crc.csum_type, nonce, data_buf, bytes);
|
||||
if (fsck_err_on(bch2_crc_cmp(csum, p.crc.csum),
|
||||
trans, dup_backpointer_to_bad_csum_extent,
|
||||
|
|
|
@ -594,6 +594,7 @@ struct bch_dev {
|
|||
#define BCH_FS_FLAGS() \
|
||||
x(new_fs) \
|
||||
x(started) \
|
||||
x(clean_recovery) \
|
||||
x(btree_running) \
|
||||
x(accounting_replay_done) \
|
||||
x(may_go_rw) \
|
||||
|
@ -776,7 +777,7 @@ struct bch_fs {
|
|||
unsigned nsec_per_time_unit;
|
||||
u64 features;
|
||||
u64 compat;
|
||||
unsigned long errors_silent[BITS_TO_LONGS(BCH_SB_ERR_MAX)];
|
||||
unsigned long errors_silent[BITS_TO_LONGS(BCH_FSCK_ERR_MAX)];
|
||||
u64 btrees_lost_data;
|
||||
} sb;
|
||||
|
||||
|
|
|
@ -217,7 +217,7 @@ struct bkey {
|
|||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
__u8 pad[1];
|
||||
|
||||
struct bversion version;
|
||||
struct bversion bversion;
|
||||
__u32 size; /* extent size, in sectors */
|
||||
struct bpos p;
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
|
@ -328,8 +328,8 @@ enum bch_bkey_fields {
|
|||
bkey_format_field(OFFSET, p.offset), \
|
||||
bkey_format_field(SNAPSHOT, p.snapshot), \
|
||||
bkey_format_field(SIZE, size), \
|
||||
bkey_format_field(VERSION_HI, version.hi), \
|
||||
bkey_format_field(VERSION_LO, version.lo), \
|
||||
bkey_format_field(VERSION_HI, bversion.hi), \
|
||||
bkey_format_field(VERSION_LO, bversion.lo), \
|
||||
}, \
|
||||
})
|
||||
|
||||
|
|
|
@ -214,9 +214,9 @@ static __always_inline int bversion_cmp(struct bversion l, struct bversion r)
|
|||
#define ZERO_VERSION ((struct bversion) { .hi = 0, .lo = 0 })
|
||||
#define MAX_VERSION ((struct bversion) { .hi = ~0, .lo = ~0ULL })
|
||||
|
||||
static __always_inline int bversion_zero(struct bversion v)
|
||||
static __always_inline bool bversion_zero(struct bversion v)
|
||||
{
|
||||
return !bversion_cmp(v, ZERO_VERSION);
|
||||
return bversion_cmp(v, ZERO_VERSION) == 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BCACHEFS_DEBUG
|
||||
|
@ -554,8 +554,8 @@ static inline void bch2_bkey_pack_test(void) {}
|
|||
x(BKEY_FIELD_OFFSET, p.offset) \
|
||||
x(BKEY_FIELD_SNAPSHOT, p.snapshot) \
|
||||
x(BKEY_FIELD_SIZE, size) \
|
||||
x(BKEY_FIELD_VERSION_HI, version.hi) \
|
||||
x(BKEY_FIELD_VERSION_LO, version.lo)
|
||||
x(BKEY_FIELD_VERSION_HI, bversion.hi) \
|
||||
x(BKEY_FIELD_VERSION_LO, bversion.lo)
|
||||
|
||||
struct bkey_format_state {
|
||||
u64 field_min[BKEY_NR_FIELDS];
|
||||
|
|
|
@ -289,7 +289,7 @@ void bch2_bkey_to_text(struct printbuf *out, const struct bkey *k)
|
|||
|
||||
bch2_bpos_to_text(out, k->p);
|
||||
|
||||
prt_printf(out, " len %u ver %llu", k->size, k->version.lo);
|
||||
prt_printf(out, " len %u ver %llu", k->size, k->bversion.lo);
|
||||
} else {
|
||||
prt_printf(out, "(null)");
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ bool bch2_bkey_normalize(struct bch_fs *, struct bkey_s);
|
|||
static inline bool bch2_bkey_maybe_mergable(const struct bkey *l, const struct bkey *r)
|
||||
{
|
||||
return l->type == r->type &&
|
||||
!bversion_cmp(l->version, r->version) &&
|
||||
!bversion_cmp(l->bversion, r->bversion) &&
|
||||
bpos_eq(l->p, bkey_start_pos(r));
|
||||
}
|
||||
|
||||
|
|
|
@ -513,6 +513,8 @@ int bch2_check_topology(struct bch_fs *c)
|
|||
struct bpos pulled_from_scan = POS_MIN;
|
||||
int ret = 0;
|
||||
|
||||
bch2_trans_srcu_unlock(trans);
|
||||
|
||||
for (unsigned i = 0; i < btree_id_nr_alive(c) && !ret; i++) {
|
||||
struct btree_root *r = bch2_btree_id_root(c, i);
|
||||
bool reconstructed_root = false;
|
||||
|
@ -599,15 +601,15 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
|
|||
|
||||
if (initial) {
|
||||
BUG_ON(bch2_journal_seq_verify &&
|
||||
k.k->version.lo > atomic64_read(&c->journal.seq));
|
||||
k.k->bversion.lo > atomic64_read(&c->journal.seq));
|
||||
|
||||
if (fsck_err_on(btree_id != BTREE_ID_accounting &&
|
||||
k.k->version.lo > atomic64_read(&c->key_version),
|
||||
k.k->bversion.lo > atomic64_read(&c->key_version),
|
||||
trans, bkey_version_in_future,
|
||||
"key version number higher than recorded %llu\n %s",
|
||||
atomic64_read(&c->key_version),
|
||||
(bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
|
||||
atomic64_set(&c->key_version, k.k->version.lo);
|
||||
atomic64_set(&c->key_version, k.k->bversion.lo);
|
||||
}
|
||||
|
||||
if (mustfix_fsck_err_on(level && !bch2_dev_btree_bitmap_marked(c, k),
|
||||
|
|
|
@ -1195,6 +1195,10 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
|
|||
set_btree_bset(b, b->set, &b->data->keys);
|
||||
|
||||
b->nr = bch2_key_sort_fix_overlapping(c, &sorted->keys, iter);
|
||||
memset((uint8_t *)(sorted + 1) + b->nr.live_u64s * sizeof(u64), 0,
|
||||
btree_buf_bytes(b) -
|
||||
sizeof(struct btree_node) -
|
||||
b->nr.live_u64s * sizeof(u64));
|
||||
|
||||
u64s = le16_to_cpu(sorted->keys.u64s);
|
||||
*sorted = *b->data;
|
||||
|
@ -1219,7 +1223,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
|
|||
ret = bch2_bkey_val_validate(c, u.s_c, READ);
|
||||
if (ret == -BCH_ERR_fsck_delete_bkey ||
|
||||
(bch2_inject_invalid_keys &&
|
||||
!bversion_cmp(u.k->version, MAX_VERSION))) {
|
||||
!bversion_cmp(u.k->bversion, MAX_VERSION))) {
|
||||
btree_keys_account_key_drop(&b->nr, 0, k);
|
||||
|
||||
i->u64s = cpu_to_le16(le16_to_cpu(i->u64s) - k->u64s);
|
||||
|
|
|
@ -275,7 +275,7 @@ static int read_btree_nodes(struct find_btree_nodes *f)
|
|||
w->ca = ca;
|
||||
|
||||
t = kthread_run(read_btree_nodes_worker, w, "read_btree_nodes/%s", ca->name);
|
||||
ret = IS_ERR_OR_NULL(t);
|
||||
ret = PTR_ERR_OR_ZERO(t);
|
||||
if (ret) {
|
||||
percpu_ref_put(&ca->io_ref);
|
||||
closure_put(&cl);
|
||||
|
|
|
@ -684,10 +684,10 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags,
|
|||
!(flags & BCH_TRANS_COMMIT_no_journal_res)) {
|
||||
if (bch2_journal_seq_verify)
|
||||
trans_for_each_update(trans, i)
|
||||
i->k->k.version.lo = trans->journal_res.seq;
|
||||
i->k->k.bversion.lo = trans->journal_res.seq;
|
||||
else if (bch2_inject_invalid_keys)
|
||||
trans_for_each_update(trans, i)
|
||||
i->k->k.version = MAX_VERSION;
|
||||
i->k->k.bversion = MAX_VERSION;
|
||||
}
|
||||
|
||||
h = trans->hooks;
|
||||
|
@ -700,27 +700,31 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags,
|
|||
|
||||
struct jset_entry *entry = trans->journal_entries;
|
||||
|
||||
if (likely(!(flags & BCH_TRANS_COMMIT_skip_accounting_apply))) {
|
||||
percpu_down_read(&c->mark_lock);
|
||||
|
||||
for (entry = trans->journal_entries;
|
||||
entry != (void *) ((u64 *) trans->journal_entries + trans->journal_entries_u64s);
|
||||
entry = vstruct_next(entry))
|
||||
if (jset_entry_is_key(entry) && entry->start->k.type == KEY_TYPE_accounting) {
|
||||
if (entry->type == BCH_JSET_ENTRY_write_buffer_keys &&
|
||||
entry->start->k.type == KEY_TYPE_accounting) {
|
||||
BUG_ON(!trans->journal_res.ref);
|
||||
|
||||
struct bkey_i_accounting *a = bkey_i_to_accounting(entry->start);
|
||||
|
||||
a->k.version = journal_pos_to_bversion(&trans->journal_res,
|
||||
a->k.bversion = journal_pos_to_bversion(&trans->journal_res,
|
||||
(u64 *) entry - (u64 *) trans->journal_entries);
|
||||
BUG_ON(bversion_zero(a->k.version));
|
||||
ret = bch2_accounting_mem_mod_locked(trans, accounting_i_to_s_c(a), false, false);
|
||||
BUG_ON(bversion_zero(a->k.bversion));
|
||||
|
||||
if (likely(!(flags & BCH_TRANS_COMMIT_skip_accounting_apply))) {
|
||||
ret = bch2_accounting_mem_mod_locked(trans, accounting_i_to_s_c(a), BCH_ACCOUNTING_normal);
|
||||
if (ret)
|
||||
goto revert_fs_usage;
|
||||
}
|
||||
}
|
||||
percpu_up_read(&c->mark_lock);
|
||||
|
||||
/* XXX: we only want to run this if deltas are nonzero */
|
||||
bch2_trans_account_disk_usage_change(trans);
|
||||
}
|
||||
|
||||
trans_for_each_update(trans, i)
|
||||
if (btree_node_type_has_atomic_triggers(i->bkey_type)) {
|
||||
|
@ -735,6 +739,40 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags,
|
|||
goto fatal_err;
|
||||
}
|
||||
|
||||
trans_for_each_update(trans, i) {
|
||||
enum bch_validate_flags invalid_flags = 0;
|
||||
|
||||
if (!(flags & BCH_TRANS_COMMIT_no_journal_res))
|
||||
invalid_flags |= BCH_VALIDATE_write|BCH_VALIDATE_commit;
|
||||
|
||||
ret = bch2_bkey_validate(c, bkey_i_to_s_c(i->k),
|
||||
i->bkey_type, invalid_flags);
|
||||
if (unlikely(ret)){
|
||||
bch2_trans_inconsistent(trans, "invalid bkey on insert from %s -> %ps\n",
|
||||
trans->fn, (void *) i->ip_allocated);
|
||||
goto fatal_err;
|
||||
}
|
||||
btree_insert_entry_checks(trans, i);
|
||||
}
|
||||
|
||||
for (struct jset_entry *i = trans->journal_entries;
|
||||
i != (void *) ((u64 *) trans->journal_entries + trans->journal_entries_u64s);
|
||||
i = vstruct_next(i)) {
|
||||
enum bch_validate_flags invalid_flags = 0;
|
||||
|
||||
if (!(flags & BCH_TRANS_COMMIT_no_journal_res))
|
||||
invalid_flags |= BCH_VALIDATE_write|BCH_VALIDATE_commit;
|
||||
|
||||
ret = bch2_journal_entry_validate(c, NULL, i,
|
||||
bcachefs_metadata_version_current,
|
||||
CPU_BIG_ENDIAN, invalid_flags);
|
||||
if (unlikely(ret)) {
|
||||
bch2_trans_inconsistent(trans, "invalid journal entry on insert from %s\n",
|
||||
trans->fn);
|
||||
goto fatal_err;
|
||||
}
|
||||
}
|
||||
|
||||
if (likely(!(flags & BCH_TRANS_COMMIT_no_journal_res))) {
|
||||
struct journal *j = &c->journal;
|
||||
struct jset_entry *entry;
|
||||
|
@ -798,7 +836,7 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, unsigned flags,
|
|||
struct bkey_s_accounting a = bkey_i_to_s_accounting(entry2->start);
|
||||
|
||||
bch2_accounting_neg(a);
|
||||
bch2_accounting_mem_mod_locked(trans, a.c, false, false);
|
||||
bch2_accounting_mem_mod_locked(trans, a.c, BCH_ACCOUNTING_normal);
|
||||
bch2_accounting_neg(a);
|
||||
}
|
||||
percpu_up_read(&c->mark_lock);
|
||||
|
@ -1019,40 +1057,6 @@ int __bch2_trans_commit(struct btree_trans *trans, unsigned flags)
|
|||
if (ret)
|
||||
goto out_reset;
|
||||
|
||||
trans_for_each_update(trans, i) {
|
||||
enum bch_validate_flags invalid_flags = 0;
|
||||
|
||||
if (!(flags & BCH_TRANS_COMMIT_no_journal_res))
|
||||
invalid_flags |= BCH_VALIDATE_write|BCH_VALIDATE_commit;
|
||||
|
||||
ret = bch2_bkey_validate(c, bkey_i_to_s_c(i->k),
|
||||
i->bkey_type, invalid_flags);
|
||||
if (unlikely(ret)){
|
||||
bch2_trans_inconsistent(trans, "invalid bkey on insert from %s -> %ps\n",
|
||||
trans->fn, (void *) i->ip_allocated);
|
||||
return ret;
|
||||
}
|
||||
btree_insert_entry_checks(trans, i);
|
||||
}
|
||||
|
||||
for (struct jset_entry *i = trans->journal_entries;
|
||||
i != (void *) ((u64 *) trans->journal_entries + trans->journal_entries_u64s);
|
||||
i = vstruct_next(i)) {
|
||||
enum bch_validate_flags invalid_flags = 0;
|
||||
|
||||
if (!(flags & BCH_TRANS_COMMIT_no_journal_res))
|
||||
invalid_flags |= BCH_VALIDATE_write|BCH_VALIDATE_commit;
|
||||
|
||||
ret = bch2_journal_entry_validate(c, NULL, i,
|
||||
bcachefs_metadata_version_current,
|
||||
CPU_BIG_ENDIAN, invalid_flags);
|
||||
if (unlikely(ret)) {
|
||||
bch2_trans_inconsistent(trans, "invalid journal entry on insert from %s\n",
|
||||
trans->fn);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely(!test_bit(BCH_FS_may_go_rw, &c->flags))) {
|
||||
ret = do_bch2_trans_commit_to_journal_replay(trans);
|
||||
goto out_reset;
|
||||
|
|
|
@ -220,7 +220,8 @@ static inline struct bkey_i *__bch2_bkey_make_mut_noupdate(struct btree_trans *t
|
|||
if (type && k.k->type != type)
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
mut = bch2_trans_kmalloc_nomemzero(trans, bytes);
|
||||
/* extra padding for varint_decode_fast... */
|
||||
mut = bch2_trans_kmalloc_nomemzero(trans, bytes + 8);
|
||||
if (!IS_ERR(mut)) {
|
||||
bkey_reassemble(mut, k);
|
||||
|
||||
|
|
|
@ -639,7 +639,7 @@ int bch2_data_update_init(struct btree_trans *trans,
|
|||
|
||||
bch2_write_op_init(&m->op, c, io_opts);
|
||||
m->op.pos = bkey_start_pos(k.k);
|
||||
m->op.version = k.k->version;
|
||||
m->op.version = k.k->bversion;
|
||||
m->op.target = data_opts.target;
|
||||
m->op.write_point = wp;
|
||||
m->op.nr_replicas = 0;
|
||||
|
|
|
@ -134,6 +134,10 @@ int bch2_accounting_validate(struct bch_fs *c, struct bkey_s_c k,
|
|||
void *end = &acc_k + 1;
|
||||
int ret = 0;
|
||||
|
||||
bkey_fsck_err_on(bversion_zero(k.k->bversion),
|
||||
c, accounting_key_version_0,
|
||||
"accounting key with version=0");
|
||||
|
||||
switch (acc_k.type) {
|
||||
case BCH_DISK_ACCOUNTING_nr_inodes:
|
||||
end = field_end(acc_k, nr_inodes);
|
||||
|
@ -291,7 +295,7 @@ static int __bch2_accounting_mem_insert(struct bch_fs *c, struct bkey_s_c_accoun
|
|||
|
||||
struct accounting_mem_entry n = {
|
||||
.pos = a.k->p,
|
||||
.version = a.k->version,
|
||||
.bversion = a.k->bversion,
|
||||
.nr_counters = bch2_accounting_counters(a.k),
|
||||
.v[0] = __alloc_percpu_gfp(n.nr_counters * sizeof(u64),
|
||||
sizeof(u64), GFP_KERNEL),
|
||||
|
@ -319,11 +323,13 @@ static int __bch2_accounting_mem_insert(struct bch_fs *c, struct bkey_s_c_accoun
|
|||
return -BCH_ERR_ENOMEM_disk_accounting;
|
||||
}
|
||||
|
||||
int bch2_accounting_mem_insert(struct bch_fs *c, struct bkey_s_c_accounting a, bool gc)
|
||||
int bch2_accounting_mem_insert(struct bch_fs *c, struct bkey_s_c_accounting a,
|
||||
enum bch_accounting_mode mode)
|
||||
{
|
||||
struct bch_replicas_padded r;
|
||||
|
||||
if (accounting_to_replicas(&r.e, a.k->p) &&
|
||||
if (mode != BCH_ACCOUNTING_read &&
|
||||
accounting_to_replicas(&r.e, a.k->p) &&
|
||||
!bch2_replicas_marked_locked(c, &r.e))
|
||||
return -BCH_ERR_btree_insert_need_mark_replicas;
|
||||
|
||||
|
@ -566,7 +572,9 @@ int bch2_gc_accounting_done(struct bch_fs *c)
|
|||
struct { __BKEY_PADDED(k, BCH_ACCOUNTING_MAX_COUNTERS); } k_i;
|
||||
|
||||
accounting_key_init(&k_i.k, &acc_k, src_v, nr);
|
||||
bch2_accounting_mem_mod_locked(trans, bkey_i_to_s_c_accounting(&k_i.k), false, false);
|
||||
bch2_accounting_mem_mod_locked(trans,
|
||||
bkey_i_to_s_c_accounting(&k_i.k),
|
||||
BCH_ACCOUNTING_normal);
|
||||
|
||||
preempt_disable();
|
||||
struct bch_fs_usage_base *dst = this_cpu_ptr(c->usage);
|
||||
|
@ -589,30 +597,14 @@ int bch2_gc_accounting_done(struct bch_fs *c)
|
|||
static int accounting_read_key(struct btree_trans *trans, struct bkey_s_c k)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
struct printbuf buf = PRINTBUF;
|
||||
|
||||
if (k.k->type != KEY_TYPE_accounting)
|
||||
return 0;
|
||||
|
||||
percpu_down_read(&c->mark_lock);
|
||||
int ret = bch2_accounting_mem_mod_locked(trans, bkey_s_c_to_accounting(k), false, true);
|
||||
int ret = bch2_accounting_mem_mod_locked(trans, bkey_s_c_to_accounting(k),
|
||||
BCH_ACCOUNTING_read);
|
||||
percpu_up_read(&c->mark_lock);
|
||||
|
||||
if (bch2_accounting_key_is_zero(bkey_s_c_to_accounting(k)) &&
|
||||
ret == -BCH_ERR_btree_insert_need_mark_replicas)
|
||||
ret = 0;
|
||||
|
||||
struct disk_accounting_pos acc;
|
||||
bpos_to_disk_accounting_pos(&acc, k.k->p);
|
||||
|
||||
if (fsck_err_on(ret == -BCH_ERR_btree_insert_need_mark_replicas,
|
||||
trans, accounting_replicas_not_marked,
|
||||
"accounting not marked in superblock replicas\n %s",
|
||||
(bch2_accounting_key_to_text(&buf, &acc),
|
||||
buf.buf)))
|
||||
ret = bch2_accounting_update_sb_one(c, k.k->p);
|
||||
fsck_err:
|
||||
printbuf_exit(&buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -624,6 +616,7 @@ int bch2_accounting_read(struct bch_fs *c)
|
|||
{
|
||||
struct bch_accounting_mem *acc = &c->accounting;
|
||||
struct btree_trans *trans = bch2_trans_get(c);
|
||||
struct printbuf buf = PRINTBUF;
|
||||
|
||||
int ret = for_each_btree_key(trans, iter,
|
||||
BTREE_ID_accounting, POS_MIN,
|
||||
|
@ -647,7 +640,7 @@ int bch2_accounting_read(struct bch_fs *c)
|
|||
accounting_pos_cmp, &k.k->p);
|
||||
|
||||
bool applied = idx < acc->k.nr &&
|
||||
bversion_cmp(acc->k.data[idx].version, k.k->version) >= 0;
|
||||
bversion_cmp(acc->k.data[idx].bversion, k.k->bversion) >= 0;
|
||||
|
||||
if (applied)
|
||||
continue;
|
||||
|
@ -655,7 +648,7 @@ int bch2_accounting_read(struct bch_fs *c)
|
|||
if (i + 1 < &darray_top(*keys) &&
|
||||
i[1].k->k.type == KEY_TYPE_accounting &&
|
||||
!journal_key_cmp(i, i + 1)) {
|
||||
BUG_ON(bversion_cmp(i[0].k->k.version, i[1].k->k.version) >= 0);
|
||||
WARN_ON(bversion_cmp(i[0].k->k.bversion, i[1].k->k.bversion) >= 0);
|
||||
|
||||
i[1].journal_seq = i[0].journal_seq;
|
||||
|
||||
|
@ -674,6 +667,45 @@ int bch2_accounting_read(struct bch_fs *c)
|
|||
keys->gap = keys->nr = dst - keys->data;
|
||||
|
||||
percpu_down_read(&c->mark_lock);
|
||||
for (unsigned i = 0; i < acc->k.nr; i++) {
|
||||
u64 v[BCH_ACCOUNTING_MAX_COUNTERS];
|
||||
bch2_accounting_mem_read_counters(acc, i, v, ARRAY_SIZE(v), false);
|
||||
|
||||
if (bch2_is_zero(v, sizeof(v[0]) * acc->k.data[i].nr_counters))
|
||||
continue;
|
||||
|
||||
struct bch_replicas_padded r;
|
||||
if (!accounting_to_replicas(&r.e, acc->k.data[i].pos))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If the replicas entry is invalid it'll get cleaned up by
|
||||
* check_allocations:
|
||||
*/
|
||||
if (bch2_replicas_entry_validate(&r.e, c, &buf))
|
||||
continue;
|
||||
|
||||
struct disk_accounting_pos k;
|
||||
bpos_to_disk_accounting_pos(&k, acc->k.data[i].pos);
|
||||
|
||||
if (fsck_err_on(!bch2_replicas_marked_locked(c, &r.e),
|
||||
trans, accounting_replicas_not_marked,
|
||||
"accounting not marked in superblock replicas\n %s",
|
||||
(printbuf_reset(&buf),
|
||||
bch2_accounting_key_to_text(&buf, &k),
|
||||
buf.buf))) {
|
||||
/*
|
||||
* We're not RW yet and still single threaded, dropping
|
||||
* and retaking lock is ok:
|
||||
*/
|
||||
percpu_up_read(&c->mark_lock);
|
||||
ret = bch2_mark_replicas(c, &r.e);
|
||||
if (ret)
|
||||
goto fsck_err;
|
||||
percpu_down_read(&c->mark_lock);
|
||||
}
|
||||
}
|
||||
|
||||
preempt_disable();
|
||||
struct bch_fs_usage_base *usage = this_cpu_ptr(c->usage);
|
||||
|
||||
|
@ -709,8 +741,10 @@ int bch2_accounting_read(struct bch_fs *c)
|
|||
}
|
||||
}
|
||||
preempt_enable();
|
||||
fsck_err:
|
||||
percpu_up_read(&c->mark_lock);
|
||||
err:
|
||||
printbuf_exit(&buf);
|
||||
bch2_trans_put(trans);
|
||||
bch_err_fn(c, ret);
|
||||
return ret;
|
||||
|
|
|
@ -36,8 +36,8 @@ static inline void bch2_accounting_accumulate(struct bkey_i_accounting *dst,
|
|||
|
||||
for (unsigned i = 0; i < bch2_accounting_counters(&dst->k); i++)
|
||||
dst->v.d[i] += src.v->d[i];
|
||||
if (bversion_cmp(dst->k.version, src.k->version) < 0)
|
||||
dst->k.version = src.k->version;
|
||||
if (bversion_cmp(dst->k.bversion, src.k->bversion) < 0)
|
||||
dst->k.bversion = src.k->bversion;
|
||||
}
|
||||
|
||||
static inline void fs_usage_data_type_to_base(struct bch_fs_usage_base *fs_usage,
|
||||
|
@ -103,23 +103,35 @@ static inline int accounting_pos_cmp(const void *_l, const void *_r)
|
|||
return bpos_cmp(*l, *r);
|
||||
}
|
||||
|
||||
int bch2_accounting_mem_insert(struct bch_fs *, struct bkey_s_c_accounting, bool);
|
||||
enum bch_accounting_mode {
|
||||
BCH_ACCOUNTING_normal,
|
||||
BCH_ACCOUNTING_gc,
|
||||
BCH_ACCOUNTING_read,
|
||||
};
|
||||
|
||||
int bch2_accounting_mem_insert(struct bch_fs *, struct bkey_s_c_accounting, enum bch_accounting_mode);
|
||||
void bch2_accounting_mem_gc(struct bch_fs *);
|
||||
|
||||
/*
|
||||
* Update in memory counters so they match the btree update we're doing; called
|
||||
* from transaction commit path
|
||||
*/
|
||||
static inline int bch2_accounting_mem_mod_locked(struct btree_trans *trans, struct bkey_s_c_accounting a, bool gc, bool read)
|
||||
static inline int bch2_accounting_mem_mod_locked(struct btree_trans *trans,
|
||||
struct bkey_s_c_accounting a,
|
||||
enum bch_accounting_mode mode)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
struct bch_accounting_mem *acc = &c->accounting;
|
||||
struct disk_accounting_pos acc_k;
|
||||
bpos_to_disk_accounting_pos(&acc_k, a.k->p);
|
||||
bool gc = mode == BCH_ACCOUNTING_gc;
|
||||
|
||||
EBUG_ON(gc && !acc->gc_running);
|
||||
|
||||
if (acc_k.type == BCH_DISK_ACCOUNTING_inum)
|
||||
return 0;
|
||||
|
||||
if (!gc && !read) {
|
||||
if (mode == BCH_ACCOUNTING_normal) {
|
||||
switch (acc_k.type) {
|
||||
case BCH_DISK_ACCOUNTING_persistent_reserved:
|
||||
trans->fs_usage_delta.reserved += acc_k.persistent_reserved.nr_replicas * a.v->d[0];
|
||||
|
@ -140,14 +152,11 @@ static inline int bch2_accounting_mem_mod_locked(struct btree_trans *trans, stru
|
|||
}
|
||||
}
|
||||
|
||||
struct bch_accounting_mem *acc = &c->accounting;
|
||||
unsigned idx;
|
||||
|
||||
EBUG_ON(gc && !acc->gc_running);
|
||||
|
||||
while ((idx = eytzinger0_find(acc->k.data, acc->k.nr, sizeof(acc->k.data[0]),
|
||||
accounting_pos_cmp, &a.k->p)) >= acc->k.nr) {
|
||||
int ret = bch2_accounting_mem_insert(c, a, gc);
|
||||
int ret = bch2_accounting_mem_insert(c, a, mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
@ -164,7 +173,7 @@ static inline int bch2_accounting_mem_mod_locked(struct btree_trans *trans, stru
|
|||
static inline int bch2_accounting_mem_add(struct btree_trans *trans, struct bkey_s_c_accounting a, bool gc)
|
||||
{
|
||||
percpu_down_read(&trans->c->mark_lock);
|
||||
int ret = bch2_accounting_mem_mod_locked(trans, a, gc, false);
|
||||
int ret = bch2_accounting_mem_mod_locked(trans, a, gc ? BCH_ACCOUNTING_gc : BCH_ACCOUNTING_normal);
|
||||
percpu_up_read(&trans->c->mark_lock);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
struct accounting_mem_entry {
|
||||
struct bpos pos;
|
||||
struct bversion version;
|
||||
struct bversion bversion;
|
||||
unsigned nr_counters;
|
||||
u64 __percpu *v[2];
|
||||
};
|
||||
|
|
|
@ -239,7 +239,19 @@ int __bch2_fsck_err(struct bch_fs *c,
|
|||
if (!c)
|
||||
c = trans->c;
|
||||
|
||||
WARN_ON(!trans && bch2_current_has_btree_trans(c));
|
||||
/*
|
||||
* Ugly: if there's a transaction in the current task it has to be
|
||||
* passed in to unlock if we prompt for user input.
|
||||
*
|
||||
* But, plumbing a transaction and transaction restarts into
|
||||
* bkey_validate() is problematic.
|
||||
*
|
||||
* So:
|
||||
* - make all bkey errors AUTOFIX, they're simple anyways (we just
|
||||
* delete the key)
|
||||
* - and we don't need to warn if we're not prompting
|
||||
*/
|
||||
WARN_ON(!(flags & FSCK_AUTOFIX) && !trans && bch2_current_has_btree_trans(c));
|
||||
|
||||
if ((flags & FSCK_CAN_FIX) &&
|
||||
test_bit(err, c->sb.errors_silent))
|
||||
|
|
|
@ -184,7 +184,7 @@ do { \
|
|||
ret = -BCH_ERR_fsck_delete_bkey; \
|
||||
goto fsck_err; \
|
||||
} \
|
||||
int _ret = __bch2_bkey_fsck_err(c, k, FSCK_CAN_FIX, \
|
||||
int _ret = __bch2_bkey_fsck_err(c, k, FSCK_CAN_FIX|FSCK_AUTOFIX,\
|
||||
BCH_FSCK_ERR_##_err_type, \
|
||||
_err_msg, ##__VA_ARGS__); \
|
||||
if (_ret != -BCH_ERR_fsck_fix && \
|
||||
|
|
|
@ -21,6 +21,49 @@
|
|||
#include <linux/bsearch.h>
|
||||
#include <linux/dcache.h> /* struct qstr */
|
||||
|
||||
static bool inode_points_to_dirent(struct bch_inode_unpacked *inode,
|
||||
struct bkey_s_c_dirent d)
|
||||
{
|
||||
return inode->bi_dir == d.k->p.inode &&
|
||||
inode->bi_dir_offset == d.k->p.offset;
|
||||
}
|
||||
|
||||
static bool dirent_points_to_inode_nowarn(struct bkey_s_c_dirent d,
|
||||
struct bch_inode_unpacked *inode)
|
||||
{
|
||||
if (d.v->d_type == DT_SUBVOL
|
||||
? le32_to_cpu(d.v->d_child_subvol) == inode->bi_subvol
|
||||
: le64_to_cpu(d.v->d_inum) == inode->bi_inum)
|
||||
return 0;
|
||||
return -BCH_ERR_ENOENT_dirent_doesnt_match_inode;
|
||||
}
|
||||
|
||||
static void dirent_inode_mismatch_msg(struct printbuf *out,
|
||||
struct bch_fs *c,
|
||||
struct bkey_s_c_dirent dirent,
|
||||
struct bch_inode_unpacked *inode)
|
||||
{
|
||||
prt_str(out, "inode points to dirent that does not point back:");
|
||||
prt_newline(out);
|
||||
bch2_bkey_val_to_text(out, c, dirent.s_c);
|
||||
prt_newline(out);
|
||||
bch2_inode_unpacked_to_text(out, inode);
|
||||
}
|
||||
|
||||
static int dirent_points_to_inode(struct bch_fs *c,
|
||||
struct bkey_s_c_dirent dirent,
|
||||
struct bch_inode_unpacked *inode)
|
||||
{
|
||||
int ret = dirent_points_to_inode_nowarn(dirent, inode);
|
||||
if (ret) {
|
||||
struct printbuf buf = PRINTBUF;
|
||||
dirent_inode_mismatch_msg(&buf, c, dirent, inode);
|
||||
bch_warn(c, "%s", buf.buf);
|
||||
printbuf_exit(&buf);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: this is handling transaction restarts without returning
|
||||
* -BCH_ERR_transaction_restart_nested, this is not how we do things anymore:
|
||||
|
@ -346,14 +389,17 @@ static int reattach_inode(struct btree_trans *trans,
|
|||
static int remove_backpointer(struct btree_trans *trans,
|
||||
struct bch_inode_unpacked *inode)
|
||||
{
|
||||
struct btree_iter iter;
|
||||
struct bkey_s_c_dirent d;
|
||||
int ret;
|
||||
if (!inode->bi_dir)
|
||||
return 0;
|
||||
|
||||
d = bch2_bkey_get_iter_typed(trans, &iter, BTREE_ID_dirents,
|
||||
POS(inode->bi_dir, inode->bi_dir_offset), 0,
|
||||
struct bch_fs *c = trans->c;
|
||||
struct btree_iter iter;
|
||||
struct bkey_s_c_dirent d =
|
||||
bch2_bkey_get_iter_typed(trans, &iter, BTREE_ID_dirents,
|
||||
SPOS(inode->bi_dir, inode->bi_dir_offset, inode->bi_snapshot), 0,
|
||||
dirent);
|
||||
ret = bkey_err(d) ?:
|
||||
int ret = bkey_err(d) ?:
|
||||
dirent_points_to_inode(c, d, inode) ?:
|
||||
__remove_dirent(trans, d.k->p);
|
||||
bch2_trans_iter_exit(trans, &iter);
|
||||
return ret;
|
||||
|
@ -371,6 +417,7 @@ static int reattach_subvol(struct btree_trans *trans, struct bkey_s_c_subvolume
|
|||
return ret;
|
||||
|
||||
ret = remove_backpointer(trans, &inode);
|
||||
if (!bch2_err_matches(ret, ENOENT))
|
||||
bch_err_msg(c, ret, "removing dirent");
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -626,12 +673,12 @@ static int ref_visible2(struct bch_fs *c,
|
|||
struct inode_walker_entry {
|
||||
struct bch_inode_unpacked inode;
|
||||
u32 snapshot;
|
||||
bool seen_this_pos;
|
||||
u64 count;
|
||||
};
|
||||
|
||||
struct inode_walker {
|
||||
bool first_this_inode;
|
||||
bool have_inodes;
|
||||
bool recalculate_sums;
|
||||
struct bpos last_pos;
|
||||
|
||||
|
@ -669,6 +716,12 @@ static int get_inodes_all_snapshots(struct btree_trans *trans,
|
|||
struct bkey_s_c k;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* We no longer have inodes for w->last_pos; clear this to avoid
|
||||
* screwing up check_i_sectors/check_subdir_count if we take a
|
||||
* transaction restart here:
|
||||
*/
|
||||
w->have_inodes = false;
|
||||
w->recalculate_sums = false;
|
||||
w->inodes.nr = 0;
|
||||
|
||||
|
@ -686,6 +739,7 @@ static int get_inodes_all_snapshots(struct btree_trans *trans,
|
|||
return ret;
|
||||
|
||||
w->first_this_inode = true;
|
||||
w->have_inodes = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -740,9 +794,6 @@ static struct inode_walker_entry *walk_inode(struct btree_trans *trans,
|
|||
int ret = get_inodes_all_snapshots(trans, w, k.k->p.inode);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
} else if (bkey_cmp(w->last_pos, k.k->p)) {
|
||||
darray_for_each(w->inodes, i)
|
||||
i->seen_this_pos = false;
|
||||
}
|
||||
|
||||
w->last_pos = k.k->p;
|
||||
|
@ -896,21 +947,6 @@ static struct bkey_s_c_dirent inode_get_dirent(struct btree_trans *trans,
|
|||
return dirent_get_by_pos(trans, iter, SPOS(inode->bi_dir, inode->bi_dir_offset, *snapshot));
|
||||
}
|
||||
|
||||
static bool inode_points_to_dirent(struct bch_inode_unpacked *inode,
|
||||
struct bkey_s_c_dirent d)
|
||||
{
|
||||
return inode->bi_dir == d.k->p.inode &&
|
||||
inode->bi_dir_offset == d.k->p.offset;
|
||||
}
|
||||
|
||||
static bool dirent_points_to_inode(struct bkey_s_c_dirent d,
|
||||
struct bch_inode_unpacked *inode)
|
||||
{
|
||||
return d.v->d_type == DT_SUBVOL
|
||||
? le32_to_cpu(d.v->d_child_subvol) == inode->bi_subvol
|
||||
: le64_to_cpu(d.v->d_inum) == inode->bi_inum;
|
||||
}
|
||||
|
||||
static int check_inode_deleted_list(struct btree_trans *trans, struct bpos p)
|
||||
{
|
||||
struct btree_iter iter;
|
||||
|
@ -920,13 +956,14 @@ static int check_inode_deleted_list(struct btree_trans *trans, struct bpos p)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int check_inode_dirent_inode(struct btree_trans *trans, struct bkey_s_c inode_k,
|
||||
static int check_inode_dirent_inode(struct btree_trans *trans,
|
||||
struct bch_inode_unpacked *inode,
|
||||
u32 inode_snapshot, bool *write_inode)
|
||||
bool *write_inode)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
struct printbuf buf = PRINTBUF;
|
||||
|
||||
u32 inode_snapshot = inode->bi_snapshot;
|
||||
struct btree_iter dirent_iter = {};
|
||||
struct bkey_s_c_dirent d = inode_get_dirent(trans, &dirent_iter, inode, &inode_snapshot);
|
||||
int ret = bkey_err(d);
|
||||
|
@ -936,13 +973,13 @@ static int check_inode_dirent_inode(struct btree_trans *trans, struct bkey_s_c i
|
|||
if (fsck_err_on(ret,
|
||||
trans, inode_points_to_missing_dirent,
|
||||
"inode points to missing dirent\n%s",
|
||||
(bch2_bkey_val_to_text(&buf, c, inode_k), buf.buf)) ||
|
||||
fsck_err_on(!ret && !dirent_points_to_inode(d, inode),
|
||||
(bch2_inode_unpacked_to_text(&buf, inode), buf.buf)) ||
|
||||
fsck_err_on(!ret && dirent_points_to_inode_nowarn(d, inode),
|
||||
trans, inode_points_to_wrong_dirent,
|
||||
"inode points to dirent that does not point back:\n%s",
|
||||
(bch2_bkey_val_to_text(&buf, c, inode_k),
|
||||
prt_newline(&buf),
|
||||
bch2_bkey_val_to_text(&buf, c, d.s_c), buf.buf))) {
|
||||
"%s",
|
||||
(printbuf_reset(&buf),
|
||||
dirent_inode_mismatch_msg(&buf, c, d, inode),
|
||||
buf.buf))) {
|
||||
/*
|
||||
* We just clear the backpointer fields for now. If we find a
|
||||
* dirent that points to this inode in check_dirents(), we'll
|
||||
|
@ -963,7 +1000,7 @@ static int check_inode_dirent_inode(struct btree_trans *trans, struct bkey_s_c i
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool bch2_inode_open(struct bch_fs *c, struct bpos p)
|
||||
static bool bch2_inode_is_open(struct bch_fs *c, struct bpos p)
|
||||
{
|
||||
subvol_inum inum = {
|
||||
.subvol = snapshot_t(c, p.snapshot)->subvol,
|
||||
|
@ -972,7 +1009,7 @@ static bool bch2_inode_open(struct bch_fs *c, struct bpos p)
|
|||
|
||||
/* snapshot tree corruption, can't safely delete */
|
||||
if (!inum.subvol) {
|
||||
bch_err_ratelimited(c, "%s(): snapshot %u has no subvol", __func__, p.snapshot);
|
||||
bch_warn_ratelimited(c, "%s(): snapshot %u has no subvol, unlinked but can't safely delete", __func__, p.snapshot);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1045,6 +1082,17 @@ static int check_inode(struct btree_trans *trans,
|
|||
}
|
||||
|
||||
if (u.bi_flags & BCH_INODE_unlinked) {
|
||||
if (!test_bit(BCH_FS_started, &c->flags)) {
|
||||
/*
|
||||
* If we're not in online fsck, don't delete unlinked
|
||||
* inodes, just make sure they're on the deleted list.
|
||||
*
|
||||
* They might be referred to by a logged operation -
|
||||
* i.e. we might have crashed in the middle of a
|
||||
* truncate on an unlinked but open file - so we want to
|
||||
* let the delete_dead_inodes kill it after resuming
|
||||
* logged ops.
|
||||
*/
|
||||
ret = check_inode_deleted_list(trans, k.k->p);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -1053,22 +1101,25 @@ static int check_inode(struct btree_trans *trans,
|
|||
trans, unlinked_inode_not_on_deleted_list,
|
||||
"inode %llu:%u unlinked, but not on deleted list",
|
||||
u.bi_inum, k.k->p.snapshot);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (u.bi_flags & BCH_INODE_unlinked &&
|
||||
!bch2_inode_open(c, k.k->p) &&
|
||||
(!c->sb.clean ||
|
||||
fsck_err(trans, inode_unlinked_but_clean,
|
||||
"filesystem marked clean, but inode %llu unlinked",
|
||||
u.bi_inum))) {
|
||||
ret = bch2_btree_bit_mod_buffered(trans, BTREE_ID_deleted_inodes, k.k->p, 1);
|
||||
if (ret)
|
||||
goto err;
|
||||
} else {
|
||||
if (fsck_err_on(bch2_inode_is_open(c, k.k->p),
|
||||
trans, inode_unlinked_and_not_open,
|
||||
"inode %llu%u unlinked and not open",
|
||||
u.bi_inum, u.bi_snapshot)) {
|
||||
ret = bch2_inode_rm_snapshot(trans, u.bi_inum, iter->pos.snapshot);
|
||||
bch_err_msg(c, ret, "in fsck deleting inode");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* i_size_dirty is vestigal, since we now have logged ops for truncate * */
|
||||
if (u.bi_flags & BCH_INODE_i_size_dirty &&
|
||||
(!c->sb.clean ||
|
||||
(!test_bit(BCH_FS_clean_recovery, &c->flags) ||
|
||||
fsck_err(trans, inode_i_size_dirty_but_clean,
|
||||
"filesystem marked clean, but inode %llu has i_size dirty",
|
||||
u.bi_inum))) {
|
||||
|
@ -1097,8 +1148,9 @@ static int check_inode(struct btree_trans *trans,
|
|||
do_update = true;
|
||||
}
|
||||
|
||||
/* i_sectors_dirty is vestigal, i_sectors is always updated transactionally */
|
||||
if (u.bi_flags & BCH_INODE_i_sectors_dirty &&
|
||||
(!c->sb.clean ||
|
||||
(!test_bit(BCH_FS_clean_recovery, &c->flags) ||
|
||||
fsck_err(trans, inode_i_sectors_dirty_but_clean,
|
||||
"filesystem marked clean, but inode %llu has i_sectors dirty",
|
||||
u.bi_inum))) {
|
||||
|
@ -1126,7 +1178,7 @@ static int check_inode(struct btree_trans *trans,
|
|||
}
|
||||
|
||||
if (u.bi_dir || u.bi_dir_offset) {
|
||||
ret = check_inode_dirent_inode(trans, k, &u, k.k->p.snapshot, &do_update);
|
||||
ret = check_inode_dirent_inode(trans, &u, &do_update);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
@ -1555,10 +1607,10 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
|
|||
struct bkey_s_c k,
|
||||
struct inode_walker *inode,
|
||||
struct snapshots_seen *s,
|
||||
struct extent_ends *extent_ends)
|
||||
struct extent_ends *extent_ends,
|
||||
struct disk_reservation *res)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
struct inode_walker_entry *i;
|
||||
struct printbuf buf = PRINTBUF;
|
||||
int ret = 0;
|
||||
|
||||
|
@ -1568,7 +1620,7 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (inode->last_pos.inode != k.k->p.inode) {
|
||||
if (inode->last_pos.inode != k.k->p.inode && inode->have_inodes) {
|
||||
ret = check_i_sectors(trans, inode);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
@ -1578,12 +1630,12 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
|
|||
if (ret)
|
||||
goto err;
|
||||
|
||||
i = walk_inode(trans, inode, k);
|
||||
ret = PTR_ERR_OR_ZERO(i);
|
||||
struct inode_walker_entry *extent_i = walk_inode(trans, inode, k);
|
||||
ret = PTR_ERR_OR_ZERO(extent_i);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = check_key_has_inode(trans, iter, inode, i, k);
|
||||
ret = check_key_has_inode(trans, iter, inode, extent_i, k);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
|
@ -1592,24 +1644,19 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
|
|||
&inode->recalculate_sums);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check inodes in reverse order, from oldest snapshots to newest,
|
||||
* starting from the inode that matches this extent's snapshot. If we
|
||||
* didn't have one, iterate over all inodes:
|
||||
* Check inodes in reverse order, from oldest snapshots to
|
||||
* newest, starting from the inode that matches this extent's
|
||||
* snapshot. If we didn't have one, iterate over all inodes:
|
||||
*/
|
||||
if (!i)
|
||||
i = &darray_last(inode->inodes);
|
||||
|
||||
for (;
|
||||
for (struct inode_walker_entry *i = extent_i ?: &darray_last(inode->inodes);
|
||||
inode->inodes.data && i >= inode->inodes.data;
|
||||
--i) {
|
||||
if (i->snapshot > k.k->p.snapshot ||
|
||||
!key_visible_in_snapshot(c, s, i->snapshot, k.k->p.snapshot))
|
||||
continue;
|
||||
|
||||
if (k.k->type != KEY_TYPE_whiteout) {
|
||||
if (fsck_err_on(!(i->inode.bi_flags & BCH_INODE_i_size_dirty) &&
|
||||
k.k->p.offset > round_up(i->inode.bi_size, block_bytes(c)) >> 9 &&
|
||||
!bkey_extent_is_reservation(k),
|
||||
|
@ -1629,13 +1676,25 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
|
|||
goto err;
|
||||
|
||||
iter->k.type = KEY_TYPE_whiteout;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bkey_extent_is_allocation(k.k))
|
||||
ret = bch2_trans_commit(trans, res, NULL, BCH_TRANS_COMMIT_no_enospc);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (bkey_extent_is_allocation(k.k)) {
|
||||
for (struct inode_walker_entry *i = extent_i ?: &darray_last(inode->inodes);
|
||||
inode->inodes.data && i >= inode->inodes.data;
|
||||
--i) {
|
||||
if (i->snapshot > k.k->p.snapshot ||
|
||||
!key_visible_in_snapshot(c, s, i->snapshot, k.k->p.snapshot))
|
||||
continue;
|
||||
|
||||
i->count += k.k->size;
|
||||
}
|
||||
|
||||
i->seen_this_pos = true;
|
||||
}
|
||||
|
||||
if (k.k->type != KEY_TYPE_whiteout) {
|
||||
|
@ -1666,13 +1725,11 @@ int bch2_check_extents(struct bch_fs *c)
|
|||
extent_ends_init(&extent_ends);
|
||||
|
||||
int ret = bch2_trans_run(c,
|
||||
for_each_btree_key_commit(trans, iter, BTREE_ID_extents,
|
||||
for_each_btree_key(trans, iter, BTREE_ID_extents,
|
||||
POS(BCACHEFS_ROOT_INO, 0),
|
||||
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k,
|
||||
&res, NULL,
|
||||
BCH_TRANS_COMMIT_no_enospc, ({
|
||||
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k, ({
|
||||
bch2_disk_reservation_put(c, &res);
|
||||
check_extent(trans, &iter, k, &w, &s, &extent_ends) ?:
|
||||
check_extent(trans, &iter, k, &w, &s, &extent_ends, &res) ?:
|
||||
check_extent_overbig(trans, &iter, k);
|
||||
})) ?:
|
||||
check_i_sectors_notnested(trans, &w));
|
||||
|
@ -1758,6 +1815,7 @@ static int check_dirent_inode_dirent(struct btree_trans *trans,
|
|||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
struct printbuf buf = PRINTBUF;
|
||||
struct btree_iter bp_iter = { NULL };
|
||||
int ret = 0;
|
||||
|
||||
if (inode_points_to_dirent(target, d))
|
||||
|
@ -1770,7 +1828,7 @@ static int check_dirent_inode_dirent(struct btree_trans *trans,
|
|||
prt_printf(&buf, "\n "),
|
||||
bch2_inode_unpacked_to_text(&buf, target),
|
||||
buf.buf)))
|
||||
goto out_noiter;
|
||||
goto err;
|
||||
|
||||
if (!target->bi_dir &&
|
||||
!target->bi_dir_offset) {
|
||||
|
@ -1779,7 +1837,6 @@ static int check_dirent_inode_dirent(struct btree_trans *trans,
|
|||
return __bch2_fsck_write_inode(trans, target, target_snapshot);
|
||||
}
|
||||
|
||||
struct btree_iter bp_iter = { NULL };
|
||||
struct bkey_s_c_dirent bp_dirent = dirent_get_by_pos(trans, &bp_iter,
|
||||
SPOS(target->bi_dir, target->bi_dir_offset, target_snapshot));
|
||||
ret = bkey_err(bp_dirent);
|
||||
|
@ -1840,7 +1897,6 @@ static int check_dirent_inode_dirent(struct btree_trans *trans,
|
|||
err:
|
||||
fsck_err:
|
||||
bch2_trans_iter_exit(trans, &bp_iter);
|
||||
out_noiter:
|
||||
printbuf_exit(&buf);
|
||||
bch_err_fn(c, ret);
|
||||
return ret;
|
||||
|
@ -2075,7 +2131,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
|
|||
if (k.k->type == KEY_TYPE_whiteout)
|
||||
goto out;
|
||||
|
||||
if (dir->last_pos.inode != k.k->p.inode) {
|
||||
if (dir->last_pos.inode != k.k->p.inode && dir->have_inodes) {
|
||||
ret = check_subdir_count(trans, dir);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
@ -2137,11 +2193,15 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
|
|||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ret = bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (d.v->d_type == DT_DIR)
|
||||
for_each_visible_inode(c, s, dir, d.k->p.snapshot, i)
|
||||
i->count++;
|
||||
}
|
||||
out:
|
||||
err:
|
||||
fsck_err:
|
||||
|
@ -2164,12 +2224,9 @@ int bch2_check_dirents(struct bch_fs *c)
|
|||
snapshots_seen_init(&s);
|
||||
|
||||
int ret = bch2_trans_run(c,
|
||||
for_each_btree_key_commit(trans, iter, BTREE_ID_dirents,
|
||||
for_each_btree_key(trans, iter, BTREE_ID_dirents,
|
||||
POS(BCACHEFS_ROOT_INO, 0),
|
||||
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots,
|
||||
k,
|
||||
NULL, NULL,
|
||||
BCH_TRANS_COMMIT_no_enospc,
|
||||
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k,
|
||||
check_dirent(trans, &iter, k, &hash_info, &dir, &target, &s)) ?:
|
||||
check_subdir_count_notnested(trans, &dir));
|
||||
|
||||
|
@ -2314,22 +2371,6 @@ static bool darray_u32_has(darray_u32 *d, u32 v)
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* We've checked that inode backpointers point to valid dirents; here, it's
|
||||
* sufficient to check that the subvolume root has a dirent:
|
||||
*/
|
||||
static int subvol_has_dirent(struct btree_trans *trans, struct bkey_s_c_subvolume s)
|
||||
{
|
||||
struct bch_inode_unpacked inode;
|
||||
int ret = bch2_inode_find_by_inum_trans(trans,
|
||||
(subvol_inum) { s.k->p.offset, le64_to_cpu(s.v->inode) },
|
||||
&inode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return inode.bi_dir != 0;
|
||||
}
|
||||
|
||||
static int check_subvol_path(struct btree_trans *trans, struct btree_iter *iter, struct bkey_s_c k)
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
|
@ -2348,14 +2389,24 @@ static int check_subvol_path(struct btree_trans *trans, struct btree_iter *iter,
|
|||
|
||||
struct bkey_s_c_subvolume s = bkey_s_c_to_subvolume(k);
|
||||
|
||||
ret = subvol_has_dirent(trans, s);
|
||||
if (ret < 0)
|
||||
struct bch_inode_unpacked subvol_root;
|
||||
ret = bch2_inode_find_by_inum_trans(trans,
|
||||
(subvol_inum) { s.k->p.offset, le64_to_cpu(s.v->inode) },
|
||||
&subvol_root);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
if (fsck_err_on(!ret,
|
||||
/*
|
||||
* We've checked that inode backpointers point to valid dirents;
|
||||
* here, it's sufficient to check that the subvolume root has a
|
||||
* dirent:
|
||||
*/
|
||||
if (fsck_err_on(!subvol_root.bi_dir,
|
||||
trans, subvol_unreachable,
|
||||
"unreachable subvolume %s",
|
||||
(bch2_bkey_val_to_text(&buf, c, s.s_c),
|
||||
prt_newline(&buf),
|
||||
bch2_inode_unpacked_to_text(&buf, &subvol_root),
|
||||
buf.buf))) {
|
||||
ret = reattach_subvol(trans, s);
|
||||
break;
|
||||
|
@ -2450,10 +2501,8 @@ static int check_path(struct btree_trans *trans, pathbuf *p, struct bkey_s_c ino
|
|||
if (ret && !bch2_err_matches(ret, ENOENT))
|
||||
break;
|
||||
|
||||
if (!ret && !dirent_points_to_inode(d, &inode)) {
|
||||
if (!ret && (ret = dirent_points_to_inode(c, d, &inode)))
|
||||
bch2_trans_iter_exit(trans, &dirent_iter);
|
||||
ret = -BCH_ERR_ENOENT_dirent_doesnt_match_inode;
|
||||
}
|
||||
|
||||
if (bch2_err_matches(ret, ENOENT)) {
|
||||
ret = 0;
|
||||
|
|
|
@ -320,9 +320,11 @@ static noinline int bch2_inode_unpack_slowpath(struct bkey_s_c k,
|
|||
int bch2_inode_unpack(struct bkey_s_c k,
|
||||
struct bch_inode_unpacked *unpacked)
|
||||
{
|
||||
if (likely(k.k->type == KEY_TYPE_inode_v3))
|
||||
return bch2_inode_unpack_v3(k, unpacked);
|
||||
return bch2_inode_unpack_slowpath(k, unpacked);
|
||||
unpacked->bi_snapshot = k.k->p.snapshot;
|
||||
|
||||
return likely(k.k->type == KEY_TYPE_inode_v3)
|
||||
? bch2_inode_unpack_v3(k, unpacked)
|
||||
: bch2_inode_unpack_slowpath(k, unpacked);
|
||||
}
|
||||
|
||||
int bch2_inode_peek_nowarn(struct btree_trans *trans,
|
||||
|
@ -557,7 +559,7 @@ static void __bch2_inode_unpacked_to_text(struct printbuf *out,
|
|||
|
||||
void bch2_inode_unpacked_to_text(struct printbuf *out, struct bch_inode_unpacked *inode)
|
||||
{
|
||||
prt_printf(out, "inum: %llu ", inode->bi_inum);
|
||||
prt_printf(out, "inum: %llu:%u ", inode->bi_inum, inode->bi_snapshot);
|
||||
__bch2_inode_unpacked_to_text(out, inode);
|
||||
}
|
||||
|
||||
|
@ -1111,7 +1113,7 @@ static int may_delete_deleted_inode(struct btree_trans *trans,
|
|||
pos.offset, pos.snapshot))
|
||||
goto delete;
|
||||
|
||||
if (c->sb.clean &&
|
||||
if (test_bit(BCH_FS_clean_recovery, &c->flags) &&
|
||||
!fsck_err(trans, deleted_inode_but_clean,
|
||||
"filesystem marked as clean but have deleted inode %llu:%u",
|
||||
pos.offset, pos.snapshot)) {
|
||||
|
|
|
@ -69,6 +69,7 @@ typedef u64 u96;
|
|||
|
||||
struct bch_inode_unpacked {
|
||||
u64 bi_inum;
|
||||
u32 bi_snapshot;
|
||||
u64 bi_journal_seq;
|
||||
__le64 bi_hash_seed;
|
||||
u64 bi_size;
|
||||
|
|
|
@ -517,7 +517,7 @@ static int __bch2_rbio_narrow_crcs(struct btree_trans *trans,
|
|||
if ((ret = bkey_err(k)))
|
||||
goto out;
|
||||
|
||||
if (bversion_cmp(k.k->version, rbio->version) ||
|
||||
if (bversion_cmp(k.k->bversion, rbio->version) ||
|
||||
!bch2_bkey_matches_ptr(c, k, rbio->pick.ptr, data_offset))
|
||||
goto out;
|
||||
|
||||
|
@ -1031,7 +1031,7 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig,
|
|||
rbio->read_pos = read_pos;
|
||||
rbio->data_btree = data_btree;
|
||||
rbio->data_pos = data_pos;
|
||||
rbio->version = k.k->version;
|
||||
rbio->version = k.k->bversion;
|
||||
rbio->promote = promote;
|
||||
INIT_WORK(&rbio->work, NULL);
|
||||
|
||||
|
|
|
@ -697,7 +697,7 @@ static void init_append_extent(struct bch_write_op *op,
|
|||
e = bkey_extent_init(op->insert_keys.top);
|
||||
e->k.p = op->pos;
|
||||
e->k.size = crc.uncompressed_size;
|
||||
e->k.version = version;
|
||||
e->k.bversion = version;
|
||||
|
||||
if (crc.csum_type ||
|
||||
crc.compression_type ||
|
||||
|
@ -1544,7 +1544,7 @@ static void bch2_write_data_inline(struct bch_write_op *op, unsigned data_len)
|
|||
|
||||
id = bkey_inline_data_init(op->insert_keys.top);
|
||||
id->k.p = op->pos;
|
||||
id->k.version = op->version;
|
||||
id->k.bversion = op->version;
|
||||
id->k.size = sectors;
|
||||
|
||||
iter = bio->bi_iter;
|
||||
|
|
|
@ -605,7 +605,7 @@ static int journal_entry_data_usage_validate(struct bch_fs *c,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (journal_entry_err_on(bch2_replicas_entry_validate(&u->r, c->disk_sb.sb, &err),
|
||||
if (journal_entry_err_on(bch2_replicas_entry_validate(&u->r, c, &err),
|
||||
c, version, jset, entry,
|
||||
journal_entry_data_usage_bad_size,
|
||||
"invalid journal entry usage: %s", err.buf)) {
|
||||
|
|
|
@ -37,6 +37,14 @@ static int resume_logged_op(struct btree_trans *trans, struct btree_iter *iter,
|
|||
const struct bch_logged_op_fn *fn = logged_op_fn(k.k->type);
|
||||
struct bkey_buf sk;
|
||||
u32 restart_count = trans->restart_count;
|
||||
struct printbuf buf = PRINTBUF;
|
||||
int ret = 0;
|
||||
|
||||
fsck_err_on(test_bit(BCH_FS_clean_recovery, &c->flags),
|
||||
trans, logged_op_but_clean,
|
||||
"filesystem marked as clean but have logged op\n%s",
|
||||
(bch2_bkey_val_to_text(&buf, c, k),
|
||||
buf.buf));
|
||||
|
||||
if (!fn)
|
||||
return 0;
|
||||
|
@ -47,8 +55,9 @@ static int resume_logged_op(struct btree_trans *trans, struct btree_iter *iter,
|
|||
fn->resume(trans, sk.k);
|
||||
|
||||
bch2_bkey_buf_exit(&sk, c);
|
||||
|
||||
return trans_was_restarted(trans, restart_count);
|
||||
fsck_err:
|
||||
printbuf_exit(&buf);
|
||||
return ret ?: trans_was_restarted(trans, restart_count);
|
||||
}
|
||||
|
||||
int bch2_resume_logged_ops(struct bch_fs *c)
|
||||
|
|
|
@ -151,7 +151,7 @@ static int bch2_journal_replay_accounting_key(struct btree_trans *trans,
|
|||
struct bkey_s_c old = bch2_btree_path_peek_slot(btree_iter_path(trans, &iter), &u);
|
||||
|
||||
/* Has this delta already been applied to the btree? */
|
||||
if (bversion_cmp(old.k->version, k->k->k.version) >= 0) {
|
||||
if (bversion_cmp(old.k->bversion, k->k->k.bversion) >= 0) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
@ -717,6 +717,8 @@ int bch2_fs_recovery(struct bch_fs *c)
|
|||
|
||||
if (c->opts.fsck)
|
||||
set_bit(BCH_FS_fsck_running, &c->flags);
|
||||
if (c->sb.clean)
|
||||
set_bit(BCH_FS_clean_recovery, &c->flags);
|
||||
|
||||
ret = bch2_blacklist_table_initialize(c);
|
||||
if (ret) {
|
||||
|
@ -862,6 +864,9 @@ int bch2_fs_recovery(struct bch_fs *c)
|
|||
|
||||
clear_bit(BCH_FS_fsck_running, &c->flags);
|
||||
|
||||
/* in case we don't run journal replay, i.e. norecovery mode */
|
||||
set_bit(BCH_FS_accounting_replay_done, &c->flags);
|
||||
|
||||
/* fsync if we fixed errors */
|
||||
if (test_bit(BCH_FS_errors_fixed, &c->flags) &&
|
||||
bch2_write_ref_tryget(c, BCH_WRITE_REF_fsync)) {
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
x(check_directory_structure, 30, PASS_ONLINE|PASS_FSCK) \
|
||||
x(check_nlinks, 31, PASS_FSCK) \
|
||||
x(resume_logged_ops, 23, PASS_ALWAYS) \
|
||||
x(delete_dead_inodes, 32, PASS_FSCK|PASS_UNCLEAN) \
|
||||
x(delete_dead_inodes, 32, PASS_ALWAYS) \
|
||||
x(fix_reflink_p, 33, 0) \
|
||||
x(set_fs_needs_rebalance, 34, 0) \
|
||||
|
||||
|
|
|
@ -367,7 +367,7 @@ static int bch2_make_extent_indirect(struct btree_trans *trans,
|
|||
r_v->k.type = bkey_type_to_indirect(&orig->k);
|
||||
r_v->k.p = reflink_iter.pos;
|
||||
bch2_key_resize(&r_v->k, orig->k.size);
|
||||
r_v->k.version = orig->k.version;
|
||||
r_v->k.bversion = orig->k.bversion;
|
||||
|
||||
set_bkey_val_bytes(&r_v->k, sizeof(__le64) + bkey_val_bytes(&orig->k));
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ void bch2_replicas_entry_to_text(struct printbuf *out,
|
|||
prt_printf(out, "]");
|
||||
}
|
||||
|
||||
int bch2_replicas_entry_validate(struct bch_replicas_entry_v1 *r,
|
||||
static int bch2_replicas_entry_validate_locked(struct bch_replicas_entry_v1 *r,
|
||||
struct bch_sb *sb,
|
||||
struct printbuf *err)
|
||||
{
|
||||
|
@ -94,6 +94,16 @@ int bch2_replicas_entry_validate(struct bch_replicas_entry_v1 *r,
|
|||
return -BCH_ERR_invalid_replicas_entry;
|
||||
}
|
||||
|
||||
int bch2_replicas_entry_validate(struct bch_replicas_entry_v1 *r,
|
||||
struct bch_fs *c,
|
||||
struct printbuf *err)
|
||||
{
|
||||
mutex_lock(&c->sb_lock);
|
||||
int ret = bch2_replicas_entry_validate_locked(r, c->disk_sb.sb, err);
|
||||
mutex_unlock(&c->sb_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void bch2_cpu_replicas_to_text(struct printbuf *out,
|
||||
struct bch_replicas_cpu *r)
|
||||
{
|
||||
|
@ -676,7 +686,7 @@ static int bch2_cpu_replicas_validate(struct bch_replicas_cpu *cpu_r,
|
|||
struct bch_replicas_entry_v1 *e =
|
||||
cpu_replicas_entry(cpu_r, i);
|
||||
|
||||
int ret = bch2_replicas_entry_validate(e, sb, err);
|
||||
int ret = bch2_replicas_entry_validate_locked(e, sb, err);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ void bch2_replicas_entry_sort(struct bch_replicas_entry_v1 *);
|
|||
void bch2_replicas_entry_to_text(struct printbuf *,
|
||||
struct bch_replicas_entry_v1 *);
|
||||
int bch2_replicas_entry_validate(struct bch_replicas_entry_v1 *,
|
||||
struct bch_sb *, struct printbuf *);
|
||||
struct bch_fs *, struct printbuf *);
|
||||
void bch2_cpu_replicas_to_text(struct printbuf *, struct bch_replicas_cpu *);
|
||||
|
||||
static inline struct bch_replicas_entry_v1 *
|
||||
|
|
|
@ -167,6 +167,7 @@ struct bch_sb_field_clean *bch2_read_superblock_clean(struct bch_fs *c)
|
|||
|
||||
ret = bch2_sb_clean_validate_late(c, clean, READ);
|
||||
if (ret) {
|
||||
kfree(clean);
|
||||
mutex_unlock(&c->sb_lock);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
|
|
@ -312,8 +312,7 @@ static void bch2_sb_downgrade_to_text(struct printbuf *out, struct bch_sb *sb,
|
|||
if (!first)
|
||||
prt_char(out, ',');
|
||||
first = false;
|
||||
unsigned e = le16_to_cpu(i->errors[j]);
|
||||
prt_str(out, e < BCH_SB_ERR_MAX ? bch2_sb_error_strs[e] : "(unknown)");
|
||||
bch2_sb_error_id_to_text(out, le16_to_cpu(i->errors[j]));
|
||||
}
|
||||
prt_newline(out);
|
||||
}
|
||||
|
@ -353,7 +352,9 @@ int bch2_sb_downgrade_update(struct bch_fs *c)
|
|||
for (unsigned i = 0; i < src->nr_errors; i++)
|
||||
dst->errors[i] = cpu_to_le16(src->errors[i]);
|
||||
|
||||
downgrade_table_extra(c, &table);
|
||||
ret = downgrade_table_extra(c, &table);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (!dst->recovery_passes[0] &&
|
||||
!dst->recovery_passes[1] &&
|
||||
|
@ -399,7 +400,7 @@ void bch2_sb_set_downgrade(struct bch_fs *c, unsigned new_minor, unsigned old_mi
|
|||
|
||||
for (unsigned j = 0; j < le16_to_cpu(i->nr_errors); j++) {
|
||||
unsigned e = le16_to_cpu(i->errors[j]);
|
||||
if (e < BCH_SB_ERR_MAX)
|
||||
if (e < BCH_FSCK_ERR_MAX)
|
||||
__set_bit(e, c->sb.errors_silent);
|
||||
if (e < sizeof(ext->errors_silent) * 8)
|
||||
__set_bit_le64(e, ext->errors_silent);
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
const char * const bch2_sb_error_strs[] = {
|
||||
#define x(t, n, ...) [n] = #t,
|
||||
BCH_SB_ERRS()
|
||||
NULL
|
||||
#undef x
|
||||
};
|
||||
|
||||
static void bch2_sb_error_id_to_text(struct printbuf *out, enum bch_sb_error_id id)
|
||||
void bch2_sb_error_id_to_text(struct printbuf *out, enum bch_sb_error_id id)
|
||||
{
|
||||
if (id < BCH_SB_ERR_MAX)
|
||||
if (id < BCH_FSCK_ERR_MAX)
|
||||
prt_str(out, bch2_sb_error_strs[id]);
|
||||
else
|
||||
prt_printf(out, "(unknown error %u)", id);
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
extern const char * const bch2_sb_error_strs[];
|
||||
|
||||
void bch2_sb_error_id_to_text(struct printbuf *, enum bch_sb_error_id);
|
||||
|
||||
extern const struct bch_sb_field_ops bch_sb_field_ops_errors;
|
||||
|
||||
void bch2_sb_error_count(struct bch_fs *, enum bch_sb_error_id);
|
||||
|
|
|
@ -210,22 +210,23 @@ enum bch_fsck_flags {
|
|||
x(inode_snapshot_mismatch, 196, 0) \
|
||||
x(inode_unlinked_but_clean, 197, 0) \
|
||||
x(inode_unlinked_but_nlink_nonzero, 198, 0) \
|
||||
x(inode_unlinked_and_not_open, 281, 0) \
|
||||
x(inode_checksum_type_invalid, 199, 0) \
|
||||
x(inode_compression_type_invalid, 200, 0) \
|
||||
x(inode_subvol_root_but_not_dir, 201, 0) \
|
||||
x(inode_i_size_dirty_but_clean, 202, 0) \
|
||||
x(inode_i_sectors_dirty_but_clean, 203, 0) \
|
||||
x(inode_i_sectors_wrong, 204, 0) \
|
||||
x(inode_dir_wrong_nlink, 205, 0) \
|
||||
x(inode_dir_multiple_links, 206, 0) \
|
||||
x(inode_multiple_links_but_nlink_0, 207, 0) \
|
||||
x(inode_wrong_backpointer, 208, 0) \
|
||||
x(inode_wrong_nlink, 209, 0) \
|
||||
x(inode_unreachable, 210, 0) \
|
||||
x(deleted_inode_but_clean, 211, 0) \
|
||||
x(deleted_inode_missing, 212, 0) \
|
||||
x(deleted_inode_is_dir, 213, 0) \
|
||||
x(deleted_inode_not_unlinked, 214, 0) \
|
||||
x(inode_i_size_dirty_but_clean, 202, FSCK_AUTOFIX) \
|
||||
x(inode_i_sectors_dirty_but_clean, 203, FSCK_AUTOFIX) \
|
||||
x(inode_i_sectors_wrong, 204, FSCK_AUTOFIX) \
|
||||
x(inode_dir_wrong_nlink, 205, FSCK_AUTOFIX) \
|
||||
x(inode_dir_multiple_links, 206, FSCK_AUTOFIX) \
|
||||
x(inode_multiple_links_but_nlink_0, 207, FSCK_AUTOFIX) \
|
||||
x(inode_wrong_backpointer, 208, FSCK_AUTOFIX) \
|
||||
x(inode_wrong_nlink, 209, FSCK_AUTOFIX) \
|
||||
x(inode_unreachable, 210, FSCK_AUTOFIX) \
|
||||
x(deleted_inode_but_clean, 211, FSCK_AUTOFIX) \
|
||||
x(deleted_inode_missing, 212, FSCK_AUTOFIX) \
|
||||
x(deleted_inode_is_dir, 213, FSCK_AUTOFIX) \
|
||||
x(deleted_inode_not_unlinked, 214, FSCK_AUTOFIX) \
|
||||
x(extent_overlapping, 215, 0) \
|
||||
x(key_in_missing_inode, 216, 0) \
|
||||
x(key_in_wrong_inode_type, 217, 0) \
|
||||
|
@ -255,7 +256,7 @@ enum bch_fsck_flags {
|
|||
x(dir_loop, 241, 0) \
|
||||
x(hash_table_key_duplicate, 242, 0) \
|
||||
x(hash_table_key_wrong_offset, 243, 0) \
|
||||
x(unlinked_inode_not_on_deleted_list, 244, 0) \
|
||||
x(unlinked_inode_not_on_deleted_list, 244, FSCK_AUTOFIX) \
|
||||
x(reflink_p_front_pad_bad, 245, 0) \
|
||||
x(journal_entry_dup_same_device, 246, 0) \
|
||||
x(inode_bi_subvol_missing, 247, 0) \
|
||||
|
@ -270,7 +271,7 @@ enum bch_fsck_flags {
|
|||
x(subvol_children_not_set, 256, 0) \
|
||||
x(subvol_children_bad, 257, 0) \
|
||||
x(subvol_loop, 258, 0) \
|
||||
x(subvol_unreachable, 259, 0) \
|
||||
x(subvol_unreachable, 259, FSCK_AUTOFIX) \
|
||||
x(btree_node_bkey_bad_u64s, 260, 0) \
|
||||
x(btree_node_topology_empty_interior_node, 261, 0) \
|
||||
x(btree_ptr_v2_min_key_bad, 262, 0) \
|
||||
|
@ -282,8 +283,8 @@ enum bch_fsck_flags {
|
|||
x(btree_ptr_v2_written_0, 268, 0) \
|
||||
x(subvol_snapshot_bad, 269, 0) \
|
||||
x(subvol_inode_bad, 270, 0) \
|
||||
x(alloc_key_stripe_sectors_wrong, 271, 0) \
|
||||
x(accounting_mismatch, 272, 0) \
|
||||
x(alloc_key_stripe_sectors_wrong, 271, FSCK_AUTOFIX) \
|
||||
x(accounting_mismatch, 272, FSCK_AUTOFIX) \
|
||||
x(accounting_replicas_not_marked, 273, 0) \
|
||||
x(invalid_btree_id, 274, 0) \
|
||||
x(alloc_key_io_time_bad, 275, 0) \
|
||||
|
@ -292,12 +293,14 @@ enum bch_fsck_flags {
|
|||
x(accounting_key_replicas_nr_devs_0, 278, FSCK_AUTOFIX) \
|
||||
x(accounting_key_replicas_nr_required_bad, 279, FSCK_AUTOFIX) \
|
||||
x(accounting_key_replicas_devs_unsorted, 280, FSCK_AUTOFIX) \
|
||||
x(accounting_key_version_0, 282, FSCK_AUTOFIX) \
|
||||
x(logged_op_but_clean, 283, FSCK_AUTOFIX) \
|
||||
x(MAX, 284, 0)
|
||||
|
||||
enum bch_sb_error_id {
|
||||
#define x(t, n, ...) BCH_FSCK_ERR_##t = n,
|
||||
BCH_SB_ERRS()
|
||||
#undef x
|
||||
BCH_SB_ERR_MAX
|
||||
};
|
||||
|
||||
struct bch_sb_field_errors {
|
||||
|
|
|
@ -169,11 +169,17 @@ static int __do_six_trylock(struct six_lock *lock, enum six_lock_type type,
|
|||
ret = -1 - SIX_LOCK_write;
|
||||
}
|
||||
} else if (type == SIX_LOCK_write && lock->readers) {
|
||||
if (try) {
|
||||
if (try)
|
||||
atomic_add(SIX_LOCK_HELD_write, &lock->state);
|
||||
smp_mb__after_atomic();
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure atomic_add happens before pcpu_read_count and
|
||||
* six_set_bitmask in slow path happens before pcpu_read_count.
|
||||
*
|
||||
* Paired with the smp_mb() in read lock fast path (per-cpu mode)
|
||||
* and the one before atomic_read in read unlock path.
|
||||
*/
|
||||
smp_mb();
|
||||
ret = !pcpu_read_count(lock);
|
||||
|
||||
if (try && !ret) {
|
||||
|
|
|
@ -469,6 +469,7 @@ static u32 bch2_snapshot_tree_oldest_subvol(struct bch_fs *c, u32 snapshot_root)
|
|||
u32 id = snapshot_root;
|
||||
u32 subvol = 0, s;
|
||||
|
||||
rcu_read_lock();
|
||||
while (id) {
|
||||
s = snapshot_t(c, id)->subvol;
|
||||
|
||||
|
@ -477,6 +478,7 @@ static u32 bch2_snapshot_tree_oldest_subvol(struct bch_fs *c, u32 snapshot_root)
|
|||
|
||||
id = bch2_snapshot_tree_next(c, id);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return subvol;
|
||||
}
|
||||
|
@ -1782,6 +1784,7 @@ static int bch2_propagate_key_to_snapshot_leaf(struct btree_trans *trans,
|
|||
new->k.p.snapshot = leaf_id;
|
||||
ret = bch2_trans_update(trans, &iter, new, 0);
|
||||
out:
|
||||
bch2_set_btree_iter_dontneed(&iter);
|
||||
bch2_trans_iter_exit(trans, &iter);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -92,33 +92,31 @@ static int check_subvol(struct btree_trans *trans,
|
|||
}
|
||||
|
||||
struct bch_inode_unpacked inode;
|
||||
struct btree_iter inode_iter = {};
|
||||
ret = bch2_inode_peek_nowarn(trans, &inode_iter, &inode,
|
||||
ret = bch2_inode_find_by_inum_nowarn_trans(trans,
|
||||
(subvol_inum) { k.k->p.offset, le64_to_cpu(subvol.v->inode) },
|
||||
0);
|
||||
bch2_trans_iter_exit(trans, &inode_iter);
|
||||
|
||||
if (ret && !bch2_err_matches(ret, ENOENT))
|
||||
return ret;
|
||||
|
||||
if (fsck_err_on(ret,
|
||||
trans, subvol_to_missing_root,
|
||||
&inode);
|
||||
if (!ret) {
|
||||
if (fsck_err_on(inode.bi_subvol != subvol.k->p.offset,
|
||||
trans, subvol_root_wrong_bi_subvol,
|
||||
"subvol root %llu:%u has wrong bi_subvol field: got %u, should be %llu",
|
||||
inode.bi_inum, inode.bi_snapshot,
|
||||
inode.bi_subvol, subvol.k->p.offset)) {
|
||||
inode.bi_subvol = subvol.k->p.offset;
|
||||
ret = __bch2_fsck_write_inode(trans, &inode, le32_to_cpu(subvol.v->snapshot));
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
} else if (bch2_err_matches(ret, ENOENT)) {
|
||||
if (fsck_err(trans, subvol_to_missing_root,
|
||||
"subvolume %llu points to missing subvolume root %llu:%u",
|
||||
k.k->p.offset, le64_to_cpu(subvol.v->inode),
|
||||
le32_to_cpu(subvol.v->snapshot))) {
|
||||
ret = bch2_subvolume_delete(trans, iter->pos.offset);
|
||||
bch_err_msg(c, ret, "deleting subvolume %llu", iter->pos.offset);
|
||||
return ret ?: -BCH_ERR_transaction_restart_nested;
|
||||
ret = ret ?: -BCH_ERR_transaction_restart_nested;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (fsck_err_on(inode.bi_subvol != subvol.k->p.offset,
|
||||
trans, subvol_root_wrong_bi_subvol,
|
||||
"subvol root %llu:%u has wrong bi_subvol field: got %u, should be %llu",
|
||||
inode.bi_inum, inode_iter.k.p.snapshot,
|
||||
inode.bi_subvol, subvol.k->p.offset)) {
|
||||
inode.bi_subvol = subvol.k->p.offset;
|
||||
ret = __bch2_fsck_write_inode(trans, &inode, le32_to_cpu(subvol.v->snapshot));
|
||||
if (ret)
|
||||
} else {
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -137,7 +135,7 @@ static int check_subvol(struct btree_trans *trans,
|
|||
"%s: snapshot tree %u not found", __func__, snapshot_tree);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err;
|
||||
|
||||
if (fsck_err_on(le32_to_cpu(st.master_subvol) != subvol.k->p.offset,
|
||||
trans, subvol_not_master_and_not_snapshot,
|
||||
|
@ -147,7 +145,7 @@ static int check_subvol(struct btree_trans *trans,
|
|||
bch2_bkey_make_mut_typed(trans, iter, &subvol.s_c, 0, subvolume);
|
||||
ret = PTR_ERR_OR_ZERO(s);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err;
|
||||
|
||||
SET_BCH_SUBVOLUME_SNAP(&s->v, true);
|
||||
}
|
||||
|
|
|
@ -799,8 +799,10 @@ static int __bch2_read_super(const char *path, struct bch_opts *opts,
|
|||
i < layout.sb_offset + layout.nr_superblocks; i++) {
|
||||
offset = le64_to_cpu(*i);
|
||||
|
||||
if (offset == opt_get(*opts, sb))
|
||||
if (offset == opt_get(*opts, sb)) {
|
||||
ret = -BCH_ERR_invalid;
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = read_one_super(sb, offset, &err);
|
||||
if (!ret)
|
||||
|
@ -1188,7 +1190,8 @@ static void bch2_sb_ext_to_text(struct printbuf *out, struct bch_sb *sb,
|
|||
le_bitvector_to_cpu(errors_silent, (void *) e->errors_silent, sizeof(e->errors_silent) * 8);
|
||||
|
||||
prt_printf(out, "Errors to silently fix:\t");
|
||||
prt_bitflags_vector(out, bch2_sb_error_strs, errors_silent, sizeof(e->errors_silent) * 8);
|
||||
prt_bitflags_vector(out, bch2_sb_error_strs, errors_silent,
|
||||
min(BCH_FSCK_ERR_MAX, sizeof(e->errors_silent) * 8));
|
||||
prt_newline(out);
|
||||
|
||||
kfree(errors_silent);
|
||||
|
|
|
@ -394,7 +394,7 @@ static int insert_test_extent(struct bch_fs *c,
|
|||
k.k_i.k.p.offset = end;
|
||||
k.k_i.k.p.snapshot = U32_MAX;
|
||||
k.k_i.k.size = end - start;
|
||||
k.k_i.k.version.lo = test_version++;
|
||||
k.k_i.k.bversion.lo = test_version++;
|
||||
|
||||
ret = bch2_btree_insert(c, BTREE_ID_extents, &k.k_i, NULL, 0, 0);
|
||||
bch_err_fn(c, ret);
|
||||
|
|
|
@ -176,9 +176,9 @@ TRACE_EVENT(dma_free,
|
|||
);
|
||||
|
||||
TRACE_EVENT(dma_map_sg,
|
||||
TP_PROTO(struct device *dev, struct scatterlist *sg, int nents,
|
||||
TP_PROTO(struct device *dev, struct scatterlist *sgl, int nents,
|
||||
int ents, enum dma_data_direction dir, unsigned long attrs),
|
||||
TP_ARGS(dev, sg, nents, ents, dir, attrs),
|
||||
TP_ARGS(dev, sgl, nents, ents, dir, attrs),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(device, dev_name(dev))
|
||||
|
@ -190,17 +190,17 @@ TRACE_EVENT(dma_map_sg,
|
|||
),
|
||||
|
||||
TP_fast_assign(
|
||||
struct scatterlist *sg;
|
||||
int i;
|
||||
|
||||
__assign_str(device);
|
||||
for (i = 0; i < nents; i++)
|
||||
((u64 *)__get_dynamic_array(phys_addrs))[i] =
|
||||
sg_phys(sg + i);
|
||||
for (i = 0; i < ents; i++) {
|
||||
for_each_sg(sgl, sg, nents, i)
|
||||
((u64 *)__get_dynamic_array(phys_addrs))[i] = sg_phys(sg);
|
||||
for_each_sg(sgl, sg, ents, i) {
|
||||
((u64 *)__get_dynamic_array(dma_addrs))[i] =
|
||||
sg_dma_address(sg + i);
|
||||
sg_dma_address(sg);
|
||||
((unsigned int *)__get_dynamic_array(lengths))[i] =
|
||||
sg_dma_len(sg + i);
|
||||
sg_dma_len(sg);
|
||||
}
|
||||
__entry->dir = dir;
|
||||
__entry->attrs = attrs;
|
||||
|
@ -222,9 +222,9 @@ TRACE_EVENT(dma_map_sg,
|
|||
);
|
||||
|
||||
TRACE_EVENT(dma_unmap_sg,
|
||||
TP_PROTO(struct device *dev, struct scatterlist *sg, int nents,
|
||||
TP_PROTO(struct device *dev, struct scatterlist *sgl, int nents,
|
||||
enum dma_data_direction dir, unsigned long attrs),
|
||||
TP_ARGS(dev, sg, nents, dir, attrs),
|
||||
TP_ARGS(dev, sgl, nents, dir, attrs),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(device, dev_name(dev))
|
||||
|
@ -234,12 +234,12 @@ TRACE_EVENT(dma_unmap_sg,
|
|||
),
|
||||
|
||||
TP_fast_assign(
|
||||
struct scatterlist *sg;
|
||||
int i;
|
||||
|
||||
__assign_str(device);
|
||||
for (i = 0; i < nents; i++)
|
||||
((u64 *)__get_dynamic_array(addrs))[i] =
|
||||
sg_phys(sg + i);
|
||||
for_each_sg(sgl, sg, nents, i)
|
||||
((u64 *)__get_dynamic_array(addrs))[i] = sg_phys(sg);
|
||||
__entry->dir = dir;
|
||||
__entry->attrs = attrs;
|
||||
),
|
||||
|
@ -290,9 +290,9 @@ DEFINE_EVENT(dma_sync_single, dma_sync_single_for_device,
|
|||
TP_ARGS(dev, dma_addr, size, dir));
|
||||
|
||||
DECLARE_EVENT_CLASS(dma_sync_sg,
|
||||
TP_PROTO(struct device *dev, struct scatterlist *sg, int nents,
|
||||
TP_PROTO(struct device *dev, struct scatterlist *sgl, int nents,
|
||||
enum dma_data_direction dir),
|
||||
TP_ARGS(dev, sg, nents, dir),
|
||||
TP_ARGS(dev, sgl, nents, dir),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(device, dev_name(dev))
|
||||
|
@ -302,14 +302,15 @@ DECLARE_EVENT_CLASS(dma_sync_sg,
|
|||
),
|
||||
|
||||
TP_fast_assign(
|
||||
struct scatterlist *sg;
|
||||
int i;
|
||||
|
||||
__assign_str(device);
|
||||
for (i = 0; i < nents; i++) {
|
||||
for_each_sg(sgl, sg, nents, i) {
|
||||
((u64 *)__get_dynamic_array(dma_addrs))[i] =
|
||||
sg_dma_address(sg + i);
|
||||
sg_dma_address(sg);
|
||||
((unsigned int *)__get_dynamic_array(lengths))[i] =
|
||||
sg_dma_len(sg + i);
|
||||
sg_dma_len(sg);
|
||||
}
|
||||
__entry->dir = dir;
|
||||
),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
CFLAGS += -O3 -Wl,-no-as-needed -Wall
|
||||
CFLAGS += -O3 -Wl,-no-as-needed -Wall -I $(top_srcdir)
|
||||
LDLIBS += -lrt -lpthread -lm
|
||||
|
||||
# these are all "safe" tests that don't modify
|
||||
|
|
|
@ -22,14 +22,12 @@
|
|||
#include <sys/time.h>
|
||||
#include <sys/timex.h>
|
||||
#include <time.h>
|
||||
#include <include/vdso/time64.h>
|
||||
|
||||
#include "../kselftest.h"
|
||||
|
||||
#define CLOCK_MONOTONIC_RAW 4
|
||||
|
||||
#define NSEC_PER_SEC 1000000000LL
|
||||
#define USEC_PER_SEC 1000000
|
||||
|
||||
#define MILLION 1000000
|
||||
|
||||
long systick;
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <include/vdso/time64.h>
|
||||
#include <errno.h>
|
||||
#include "../kselftest.h"
|
||||
|
||||
#define CLOCK_REALTIME 0
|
||||
|
@ -45,7 +47,6 @@
|
|||
#define NR_CLOCKIDS 12
|
||||
|
||||
|
||||
#define NSEC_PER_SEC 1000000000ULL
|
||||
#define UNREASONABLE_LAT (NSEC_PER_SEC * 5) /* hopefully we resume in 5 secs */
|
||||
|
||||
#define SUSPEND_SECS 15
|
||||
|
@ -142,8 +143,8 @@ int main(void)
|
|||
|
||||
alarmcount = 0;
|
||||
if (timer_create(alarm_clock_id, &se, &tm1) == -1) {
|
||||
printf("timer_create failed, %s unsupported?\n",
|
||||
clockstring(alarm_clock_id));
|
||||
printf("timer_create failed, %s unsupported?: %s\n",
|
||||
clockstring(alarm_clock_id), strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,10 +28,10 @@
|
|||
#include <sys/timex.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <include/vdso/time64.h>
|
||||
#include "../kselftest.h"
|
||||
|
||||
#define CALLS_PER_LOOP 64
|
||||
#define NSEC_PER_SEC 1000000000ULL
|
||||
|
||||
#define CLOCK_REALTIME 0
|
||||
#define CLOCK_MONOTONIC 1
|
||||
|
|
|
@ -48,9 +48,9 @@
|
|||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <include/vdso/time64.h>
|
||||
#include "../kselftest.h"
|
||||
|
||||
#define NSEC_PER_SEC 1000000000ULL
|
||||
#define CLOCK_TAI 11
|
||||
|
||||
time_t next_leap;
|
||||
|
|
|
@ -29,9 +29,9 @@
|
|||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <mqueue.h>
|
||||
#include <include/vdso/time64.h>
|
||||
#include "../kselftest.h"
|
||||
|
||||
#define NSEC_PER_SEC 1000000000ULL
|
||||
|
||||
#define TARGET_TIMEOUT 100000000 /* 100ms in nanoseconds */
|
||||
#define UNRESONABLE_LATENCY 40000000 /* 40ms in nanosecs */
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue