This is the 5.4.215 stable release
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAmM0DhEACgkQONu9yGCS aT4CBA/9FmkhfUpJXWhlEAHaZX/aiskQS1vgauXP/TBy/8InVr/kY8sD6n5RUsi0 Qkt3M4a+VDsKBPiyRV+KgfiHA4Sms09IRcRpFmwslR8OzPkmZBApqHoeQCCu+/kt OTFsbiHa+tfFhOOyAXL7Q0an+yOHxPe+/RxokBYDknp1CAWbVgDTLWGY2EfX6Xa6 EjsjTKwb3WkDfbAgdvnblYcQkfUJB3kF3tk8yZnyPWQ/soZMrzVroocAK6JgzzXi hO+VHG7yfC0gTF4w4R+DY5qPzCO6I7cq5K2fL7PFzwDX7D8uotaDS8QNHPyxsjZW gLltTdhEa2HZyjTnuUeiXBmQ5vA6pLULcHP96neUWB+vULDIqXzi/TKyq6Ybetak 3yQgldQB81apEzKTRMaQKPqoNlP11qfq1jsGIFXKY5ZPxNL2IOuePA8+LGFXO2/H KrALeTmPe+f3vLyf/tDdDTM3fHWmN3bKwyxCXCdR5hvqCBWsExA+Q64NEZ24PYZ6 O5SFhEvTMpuAWpeMiiAsftuxC/OnyTzPdCzMUfiWrk1UDYcYxYSxdOpGd18St+ir 1OzhI+TO/R2heMhAHBsxrHBzO4ZdFhK+nCivPRSzyPSITyD7rMJdxE3cNJDWc9Ye DnIBm6IGJGo3rCCnPXFEsWulvElwDU0+QWxeX3uxIYkEKxbeMPo= =gmE/ -----END PGP SIGNATURE----- Merge 5.4.215 into android11-5.4-lts Changes in 5.4.215 of: fdt: fix off-by-one error in unflatten_dt_nodes() NFSv4: Turn off open-by-filehandle and NFS re-export for NFSv4.0 gpio: mpc8xxx: Fix support for IRQ_TYPE_LEVEL_LOW flow_type in mpc85xx drm/meson: Correct OSD1 global alpha value drm/meson: Fix OSD1 RGB to YCbCr coefficient parisc: ccio-dma: Add missing iounmap in error path in ccio_probe() ALSA: pcm: oss: Fix race at SNDCTL_DSP_SYNC task_stack, x86/cea: Force-inline stack helpers tracing: hold caller_addr to hardirq_{enable,disable}_ip cifs: revalidate mapping when doing direct writes cifs: don't send down the destination address to sendmsg for a SOCK_STREAM MAINTAINERS: add Chandan as xfs maintainer for 5.4.y iomap: iomap that extends beyond EOF should be marked dirty ASoC: nau8824: Fix semaphore unbalance at error paths regulator: pfuze100: Fix the global-out-of-bounds access in pfuze100_regulator_probe() rxrpc: Fix local destruction being repeated rxrpc: Fix calc of resend age ALSA: hda/sigmatel: Keep power up while beep is enabled ALSA: hda/tegra: Align BDL entry to 4KB boundary net: usb: qmi_wwan: add Quectel RM520N afs: Return -EAGAIN, not -EREMOTEIO, when a file already locked MIPS: OCTEON: irq: Fix octeon_irq_force_ciu_mapping() mksysmap: Fix the mismatch of 'L0' symbols in System.map video: fbdev: pxa3xx-gcu: Fix integer overflow in pxa3xx_gcu_write cgroup: Add missing cpus_read_lock() to cgroup_attach_task_all() ALSA: hda/sigmatel: Fix unused variable warning for beep power change usb: dwc3: gadget: Avoid starting DWC3 gadget during UDC unbind usb: dwc3: Issue core soft reset before enabling run/stop usb: dwc3: gadget: Prevent repeat pullup() usb: dwc3: gadget: Refactor pullup() usb: dwc3: gadget: Don't modify GEVNTCOUNT in pullup() usb: dwc3: gadget: Avoid duplicate requests to enable Run/Stop usb: xhci-mtk: get the microframe boundary for ESIT usb: xhci-mtk: add only one extra CS for FS/LS INTR usb: xhci-mtk: use @sch_tt to check whether need do TT schedule usb: xhci-mtk: add a function to (un)load bandwidth info usb: xhci-mtk: add some schedule error number usb: xhci-mtk: allow multiple Start-Split in a microframe usb: xhci-mtk: relax TT periodic bandwidth allocation wifi: mac80211: Fix UAF in ieee80211_scan_rx() tty/serial: atmel: RS485 & ISO7816: wait for TXRDY before sending data serial: atmel: remove redundant assignment in rs485_config tty: serial: atmel: Preserve previous USART mode if RS485 disabled usb: add quirks for Lenovo OneLink+ Dock usb: gadget: udc-xilinx: replace memcpy with memcpy_toio usb: cdns3: fix issue with rearming ISO OUT endpoint Revert "usb: add quirks for Lenovo OneLink+ Dock" Revert "usb: gadget: udc-xilinx: replace memcpy with memcpy_toio" USB: core: Fix RST error in hub.c USB: serial: option: add Quectel BG95 0x0203 composition USB: serial: option: add Quectel RM520N ALSA: hda/tegra: set depop delay for tegra ALSA: hda: add Intel 5 Series / 3400 PCI DID ALSA: hda/realtek: Add quirk for Huawei WRT-WX9 ALSA: hda/realtek: Re-arrange quirk table entries ALSA: hda/realtek: Add pincfg for ASUS G513 HP jack ALSA: hda/realtek: Add pincfg for ASUS G533Z HP jack ALSA: hda/realtek: Add quirk for ASUS GA503R laptop ALSA: hda/realtek: Enable 4-speaker output Dell Precision 5530 laptop efi: libstub: check Shim mode using MokSBStateRT mm/slub: fix to return errno if kmalloc() fails arm64: dts: rockchip: Pull up wlan wake# on Gru-Bob arm64: dts: rockchip: Set RK3399-Gru PCLK_EDP to 24 MHz arm64: dts: rockchip: Remove 'enable-active-low' from rk3399-puma netfilter: nf_conntrack_sip: fix ct_sip_walk_headers netfilter: nf_conntrack_irc: Tighten matching on DCC message netfilter: nfnetlink_osf: fix possible bogus match in nf_osf_find() iavf: Fix cached head and tail value for iavf_get_tx_pending ipvlan: Fix out-of-bound bugs caused by unset skb->mac_header net: team: Unsync device addresses on ndo_stop MIPS: lantiq: export clk_get_io() for lantiq_wdt.ko MIPS: Loongson32: Fix PHY-mode being left unspecified iavf: Fix bad page state iavf: Fix set max MTU size with port VLAN and jumbo frames i40e: Fix VF set max MTU size i40e: Fix set max_tx_rate when it is lower than 1 Mbps of: mdio: Add of_node_put() when breaking out of for_each_xx net/sched: taprio: avoid disabling offload when it was never enabled net/sched: taprio: make qdisc_leaf() see the per-netdev-queue pfifo child qdiscs netfilter: ebtables: fix memory leak when blob is malformed can: gs_usb: gs_can_open(): fix race dev->can.state condition perf jit: Include program header in ELF files perf kcore_copy: Do not check /proc/modules is unchanged net: sunhme: Fix packet reception for len < RX_COPY_THRESHOLD net: sched: fix possible refcount leak in tc_new_tfilter() serial: Create uart_xmit_advance() serial: tegra: Use uart_xmit_advance(), fixes icount.tx accounting serial: tegra-tcu: Use uart_xmit_advance(), fixes icount.tx accounting s390/dasd: fix Oops in dasd_alias_get_start_dev due to missing pavgroup usb: xhci-mtk: fix issue of out-of-bounds array access cifs: always initialize struct msghdr smb_msg completely Drivers: hv: Never allocate anything besides framebuffer from framebuffer memory region drm/amdgpu: use dirty framebuffer helper drm/amd/display: Limit user regamma to a valid value drm/rockchip: Fix return type of cdn_dp_connector_mode_valid workqueue: don't skip lockdep work dependency in cancel_work_sync() ext4: fix bug in extents parsing when eh_entries == 0 and eh_depth > 0 xfs: replace -EIO with -EFSCORRUPTED for corrupt metadata xfs: slightly tweak an assert in xfs_fs_map_blocks xfs: add missing assert in xfs_fsmap_owner_from_rmap xfs: range check ri_cnt when recovering log items xfs: attach dquots and reserve quota blocks during unwritten conversion xfs: Fix deadlock between AGI and AGF when target_ip exists in xfs_rename() xfs: convert EIO to EFSCORRUPTED when log contents are invalid xfs: constify the buffer pointer arguments to error functions xfs: always log corruption errors xfs: fix some memory leaks in log recovery xfs: stabilize insert range start boundary to avoid COW writeback race xfs: use bitops interface for buf log item AIL flag check xfs: refactor agfl length computation function xfs: split the sunit parameter update into two parts xfs: don't commit sunit/swidth updates to disk if that would cause repair failures xfs: fix an ABBA deadlock in xfs_rename xfs: fix use-after-free when aborting corrupt attr inactivation ext4: make directory inode spreading reflect flexbg size Linux 5.4.215 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: Ic4723318e38b6d2502091cfb41fe602e59c1a538
This commit is contained in:
commit
79e1dca55a
@ -17876,7 +17876,8 @@ S: Supported
|
||||
F: sound/xen/*
|
||||
|
||||
XFS FILESYSTEM
|
||||
M: Darrick J. Wong <darrick.wong@oracle.com>
|
||||
M: Chandan Babu R <chandan.babu@oracle.com>
|
||||
M: Darrick J. Wong <djwong@kernel.org>
|
||||
M: linux-xfs@vger.kernel.org
|
||||
L: linux-xfs@vger.kernel.org
|
||||
W: http://xfs.org/
|
||||
|
2
Makefile
2
Makefile
@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 5
|
||||
PATCHLEVEL = 4
|
||||
SUBLEVEL = 214
|
||||
SUBLEVEL = 215
|
||||
EXTRAVERSION =
|
||||
NAME = Kleptomaniac Octopus
|
||||
|
||||
|
@ -77,3 +77,8 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&wlan_host_wake_l {
|
||||
/* Kevin has an external pull up, but Bob does not. */
|
||||
rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>;
|
||||
};
|
||||
|
@ -237,6 +237,14 @@
|
||||
&edp {
|
||||
status = "okay";
|
||||
|
||||
/*
|
||||
* eDP PHY/clk don't sync reliably at anything other than 24 MHz. Only
|
||||
* set this here, because rk3399-gru.dtsi ensures we can generate this
|
||||
* off GPLL=600MHz, whereas some other RK3399 boards may not.
|
||||
*/
|
||||
assigned-clocks = <&cru PCLK_EDP>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
|
||||
ports {
|
||||
edp_out: port@1 {
|
||||
reg = <1>;
|
||||
@ -397,6 +405,7 @@ ap_i2c_tp: &i2c5 {
|
||||
};
|
||||
|
||||
wlan_host_wake_l: wlan-host-wake-l {
|
||||
/* Kevin has an external pull up, but Bob does not */
|
||||
rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
};
|
||||
|
@ -102,7 +102,6 @@
|
||||
vcc5v0_host: vcc5v0-host-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
gpio = <&gpio4 RK_PA3 GPIO_ACTIVE_LOW>;
|
||||
enable-active-low;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&vcc5v0_host_en>;
|
||||
regulator-name = "vcc5v0_host";
|
||||
|
@ -127,6 +127,16 @@ static void octeon_irq_free_cd(struct irq_domain *d, unsigned int irq)
|
||||
static int octeon_irq_force_ciu_mapping(struct irq_domain *domain,
|
||||
int irq, int line, int bit)
|
||||
{
|
||||
struct device_node *of_node;
|
||||
int ret;
|
||||
|
||||
of_node = irq_domain_get_of_node(domain);
|
||||
if (!of_node)
|
||||
return -EINVAL;
|
||||
ret = irq_alloc_desc_at(irq, of_node_to_nid(of_node));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return irq_domain_associate(domain, irq, line << 6 | bit);
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,7 @@ struct clk *clk_get_io(void)
|
||||
{
|
||||
return &cpu_clk_generic[2];
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clk_get_io);
|
||||
|
||||
struct clk *clk_get_ppe(void)
|
||||
{
|
||||
|
@ -98,7 +98,7 @@ int ls1x_eth_mux_init(struct platform_device *pdev, void *priv)
|
||||
if (plat_dat->bus_id) {
|
||||
__raw_writel(__raw_readl(LS1X_MUX_CTRL0) | GMAC1_USE_UART1 |
|
||||
GMAC1_USE_UART0, LS1X_MUX_CTRL0);
|
||||
switch (plat_dat->interface) {
|
||||
switch (plat_dat->phy_interface) {
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
val &= ~(GMAC1_USE_TXCLK | GMAC1_USE_PWM23);
|
||||
break;
|
||||
@ -107,12 +107,12 @@ int ls1x_eth_mux_init(struct platform_device *pdev, void *priv)
|
||||
break;
|
||||
default:
|
||||
pr_err("unsupported mii mode %d\n",
|
||||
plat_dat->interface);
|
||||
plat_dat->phy_interface);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
val &= ~GMAC1_SHUT;
|
||||
} else {
|
||||
switch (plat_dat->interface) {
|
||||
switch (plat_dat->phy_interface) {
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
val &= ~(GMAC0_USE_TXCLK | GMAC0_USE_PWM01);
|
||||
break;
|
||||
@ -121,7 +121,7 @@ int ls1x_eth_mux_init(struct platform_device *pdev, void *priv)
|
||||
break;
|
||||
default:
|
||||
pr_err("unsupported mii mode %d\n",
|
||||
plat_dat->interface);
|
||||
plat_dat->phy_interface);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
val &= ~GMAC0_SHUT;
|
||||
@ -131,7 +131,7 @@ int ls1x_eth_mux_init(struct platform_device *pdev, void *priv)
|
||||
plat_dat = dev_get_platdata(&pdev->dev);
|
||||
|
||||
val &= ~PHY_INTF_SELI;
|
||||
if (plat_dat->interface == PHY_INTERFACE_MODE_RMII)
|
||||
if (plat_dat->phy_interface == PHY_INTERFACE_MODE_RMII)
|
||||
val |= 0x4 << PHY_INTF_SELI_SHIFT;
|
||||
__raw_writel(val, LS1X_MUX_CTRL1);
|
||||
|
||||
@ -146,9 +146,9 @@ static struct plat_stmmacenet_data ls1x_eth0_pdata = {
|
||||
.bus_id = 0,
|
||||
.phy_addr = -1,
|
||||
#if defined(CONFIG_LOONGSON1_LS1B)
|
||||
.interface = PHY_INTERFACE_MODE_MII,
|
||||
.phy_interface = PHY_INTERFACE_MODE_MII,
|
||||
#elif defined(CONFIG_LOONGSON1_LS1C)
|
||||
.interface = PHY_INTERFACE_MODE_RMII,
|
||||
.phy_interface = PHY_INTERFACE_MODE_RMII,
|
||||
#endif
|
||||
.mdio_bus_data = &ls1x_mdio_bus_data,
|
||||
.dma_cfg = &ls1x_eth_dma_cfg,
|
||||
@ -186,7 +186,7 @@ struct platform_device ls1x_eth0_pdev = {
|
||||
static struct plat_stmmacenet_data ls1x_eth1_pdata = {
|
||||
.bus_id = 1,
|
||||
.phy_addr = -1,
|
||||
.interface = PHY_INTERFACE_MODE_MII,
|
||||
.phy_interface = PHY_INTERFACE_MODE_MII,
|
||||
.mdio_bus_data = &ls1x_mdio_bus_data,
|
||||
.dma_cfg = &ls1x_eth_dma_cfg,
|
||||
.has_gmac = 1,
|
||||
|
@ -133,7 +133,7 @@ extern void cea_set_pte(void *cea_vaddr, phys_addr_t pa, pgprot_t flags);
|
||||
|
||||
extern struct cpu_entry_area *get_cpu_entry_area(int cpu);
|
||||
|
||||
static inline struct entry_stack *cpu_entry_stack(int cpu)
|
||||
static __always_inline struct entry_stack *cpu_entry_stack(int cpu)
|
||||
{
|
||||
return &get_cpu_entry_area(cpu)->entry_stack_page.stack;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ static const efi_char16_t efi_SetupMode_name[] = L"SetupMode";
|
||||
|
||||
/* SHIM variables */
|
||||
static const efi_guid_t shim_guid = EFI_SHIM_LOCK_GUID;
|
||||
static const efi_char16_t shim_MokSBState_name[] = L"MokSBState";
|
||||
static const efi_char16_t shim_MokSBState_name[] = L"MokSBStateRT";
|
||||
|
||||
#define get_efi_var(name, vendor, ...) \
|
||||
efi_call_runtime(get_variable, \
|
||||
@ -58,8 +58,8 @@ enum efi_secureboot_mode efi_get_secureboot(efi_system_table_t *sys_table_arg)
|
||||
|
||||
/*
|
||||
* See if a user has put the shim into insecure mode. If so, and if the
|
||||
* variable doesn't have the runtime attribute set, we might as well
|
||||
* honor that.
|
||||
* variable doesn't have the non-volatile attribute set, we might as
|
||||
* well honor that.
|
||||
*/
|
||||
size = sizeof(moksbstate);
|
||||
status = get_efi_var(shim_MokSBState_name, &shim_guid,
|
||||
@ -68,7 +68,7 @@ enum efi_secureboot_mode efi_get_secureboot(efi_system_table_t *sys_table_arg)
|
||||
/* If it fails, we don't care why. Default to secure */
|
||||
if (status != EFI_SUCCESS)
|
||||
goto secure_boot_enabled;
|
||||
if (!(attr & EFI_VARIABLE_RUNTIME_ACCESS) && moksbstate == 1)
|
||||
if (!(attr & EFI_VARIABLE_NON_VOLATILE) && moksbstate == 1)
|
||||
return efi_secureboot_mode_disabled;
|
||||
|
||||
secure_boot_enabled:
|
||||
|
@ -190,6 +190,7 @@ static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
|
||||
|
||||
switch (flow_type) {
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
|
||||
gc->write_reg(mpc8xxx_gc->regs + GPIO_ICR,
|
||||
gc->read_reg(mpc8xxx_gc->regs + GPIO_ICR)
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_damage_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
@ -495,6 +496,7 @@ bool amdgpu_display_ddc_probe(struct amdgpu_connector *amdgpu_connector,
|
||||
static const struct drm_framebuffer_funcs amdgpu_fb_funcs = {
|
||||
.destroy = drm_gem_fb_destroy,
|
||||
.create_handle = drm_gem_fb_create_handle,
|
||||
.dirty = drm_atomic_helper_dirtyfb,
|
||||
};
|
||||
|
||||
uint32_t amdgpu_display_supported_domains(struct amdgpu_device *adev,
|
||||
|
@ -1486,6 +1486,7 @@ static void interpolate_user_regamma(uint32_t hw_points_num,
|
||||
struct fixed31_32 lut2;
|
||||
struct fixed31_32 delta_lut;
|
||||
struct fixed31_32 delta_index;
|
||||
const struct fixed31_32 one = dc_fixpt_from_int(1);
|
||||
|
||||
i = 0;
|
||||
/* fixed_pt library has problems handling too small values */
|
||||
@ -1514,6 +1515,9 @@ static void interpolate_user_regamma(uint32_t hw_points_num,
|
||||
} else
|
||||
hw_x = coordinates_x[i].x;
|
||||
|
||||
if (dc_fixpt_le(one, hw_x))
|
||||
hw_x = one;
|
||||
|
||||
norm_x = dc_fixpt_mul(norm_factor, hw_x);
|
||||
index = dc_fixpt_floor(norm_x);
|
||||
if (index < 0 || index > 255)
|
||||
|
@ -128,7 +128,7 @@ static void meson_plane_atomic_update(struct drm_plane *plane,
|
||||
|
||||
/* Enable OSD and BLK0, set max global alpha */
|
||||
priv->viu.osd1_ctrl_stat = OSD_ENABLE |
|
||||
(0xFF << OSD_GLOBAL_ALPHA_SHIFT) |
|
||||
(0x100 << OSD_GLOBAL_ALPHA_SHIFT) |
|
||||
OSD_BLK0_ENABLE;
|
||||
|
||||
canvas_id_osd1 = priv->canvas_id_osd1;
|
||||
|
@ -91,7 +91,7 @@ static void meson_viu_set_g12a_osd1_matrix(struct meson_drm *priv,
|
||||
priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12));
|
||||
writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
|
||||
priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21));
|
||||
writel((m[11] & 0x1fff) << 16,
|
||||
writel((m[11] & 0x1fff),
|
||||
priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF22));
|
||||
|
||||
writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
|
||||
|
@ -275,8 +275,9 @@ static int cdn_dp_connector_get_modes(struct drm_connector *connector)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cdn_dp_connector_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
static enum drm_mode_status
|
||||
cdn_dp_connector_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct cdn_dp_device *dp = connector_to_dp(connector);
|
||||
struct drm_display_info *display_info = &dp->connector.display_info;
|
||||
|
@ -2075,7 +2075,7 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
|
||||
bool fb_overlap_ok)
|
||||
{
|
||||
struct resource *iter, *shadow;
|
||||
resource_size_t range_min, range_max, start;
|
||||
resource_size_t range_min, range_max, start, end;
|
||||
const char *dev_n = dev_name(&device_obj->device);
|
||||
int retval;
|
||||
|
||||
@ -2110,6 +2110,14 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
|
||||
range_max = iter->end;
|
||||
start = (range_min + align - 1) & ~(align - 1);
|
||||
for (; start + size - 1 <= range_max; start += align) {
|
||||
end = start + size - 1;
|
||||
|
||||
/* Skip the whole fb_mmio region if not fb_overlap_ok */
|
||||
if (!fb_overlap_ok && fb_mmio &&
|
||||
(((start >= fb_mmio->start) && (start <= fb_mmio->end)) ||
|
||||
((end >= fb_mmio->start) && (end <= fb_mmio->end))))
|
||||
continue;
|
||||
|
||||
shadow = __request_region(iter, start, size, NULL,
|
||||
IORESOURCE_BUSY);
|
||||
if (!shadow)
|
||||
|
@ -678,6 +678,7 @@ static int gs_can_open(struct net_device *netdev)
|
||||
flags |= GS_CAN_MODE_TRIPLE_SAMPLE;
|
||||
|
||||
/* finally start device */
|
||||
dev->can.state = CAN_STATE_ERROR_ACTIVE;
|
||||
dm->mode = cpu_to_le32(GS_CAN_MODE_START);
|
||||
dm->flags = cpu_to_le32(flags);
|
||||
rc = usb_control_msg(interface_to_usbdev(dev->iface),
|
||||
@ -694,13 +695,12 @@ static int gs_can_open(struct net_device *netdev)
|
||||
if (rc < 0) {
|
||||
netdev_err(netdev, "Couldn't start device (err=%d)\n", rc);
|
||||
kfree(dm);
|
||||
dev->can.state = CAN_STATE_STOPPED;
|
||||
return rc;
|
||||
}
|
||||
|
||||
kfree(dm);
|
||||
|
||||
dev->can.state = CAN_STATE_ERROR_ACTIVE;
|
||||
|
||||
parent->active_channels++;
|
||||
if (!(dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
|
||||
netif_start_queue(netdev);
|
||||
|
@ -5638,6 +5638,26 @@ static int i40e_get_link_speed(struct i40e_vsi *vsi)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_bw_bytes_to_mbits - Convert max_tx_rate from bytes to mbits
|
||||
* @vsi: Pointer to vsi structure
|
||||
* @max_tx_rate: max TX rate in bytes to be converted into Mbits
|
||||
*
|
||||
* Helper function to convert units before send to set BW limit
|
||||
**/
|
||||
static u64 i40e_bw_bytes_to_mbits(struct i40e_vsi *vsi, u64 max_tx_rate)
|
||||
{
|
||||
if (max_tx_rate < I40E_BW_MBPS_DIVISOR) {
|
||||
dev_warn(&vsi->back->pdev->dev,
|
||||
"Setting max tx rate to minimum usable value of 50Mbps.\n");
|
||||
max_tx_rate = I40E_BW_CREDIT_DIVISOR;
|
||||
} else {
|
||||
do_div(max_tx_rate, I40E_BW_MBPS_DIVISOR);
|
||||
}
|
||||
|
||||
return max_tx_rate;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_set_bw_limit - setup BW limit for Tx traffic based on max_tx_rate
|
||||
* @vsi: VSI to be configured
|
||||
@ -5660,10 +5680,10 @@ int i40e_set_bw_limit(struct i40e_vsi *vsi, u16 seid, u64 max_tx_rate)
|
||||
max_tx_rate, seid);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (max_tx_rate && max_tx_rate < 50) {
|
||||
if (max_tx_rate && max_tx_rate < I40E_BW_CREDIT_DIVISOR) {
|
||||
dev_warn(&pf->pdev->dev,
|
||||
"Setting max tx rate to minimum usable value of 50Mbps.\n");
|
||||
max_tx_rate = 50;
|
||||
max_tx_rate = I40E_BW_CREDIT_DIVISOR;
|
||||
}
|
||||
|
||||
/* Tx rate credits are in values of 50Mbps, 0 is disabled */
|
||||
@ -7591,9 +7611,9 @@ static int i40e_setup_tc(struct net_device *netdev, void *type_data)
|
||||
|
||||
if (pf->flags & I40E_FLAG_TC_MQPRIO) {
|
||||
if (vsi->mqprio_qopt.max_rate[0]) {
|
||||
u64 max_tx_rate = vsi->mqprio_qopt.max_rate[0];
|
||||
u64 max_tx_rate = i40e_bw_bytes_to_mbits(vsi,
|
||||
vsi->mqprio_qopt.max_rate[0]);
|
||||
|
||||
do_div(max_tx_rate, I40E_BW_MBPS_DIVISOR);
|
||||
ret = i40e_set_bw_limit(vsi, vsi->seid, max_tx_rate);
|
||||
if (!ret) {
|
||||
u64 credits = max_tx_rate;
|
||||
@ -10247,10 +10267,10 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
|
||||
}
|
||||
|
||||
if (vsi->mqprio_qopt.max_rate[0]) {
|
||||
u64 max_tx_rate = vsi->mqprio_qopt.max_rate[0];
|
||||
u64 max_tx_rate = i40e_bw_bytes_to_mbits(vsi,
|
||||
vsi->mqprio_qopt.max_rate[0]);
|
||||
u64 credits = 0;
|
||||
|
||||
do_div(max_tx_rate, I40E_BW_MBPS_DIVISOR);
|
||||
ret = i40e_set_bw_limit(vsi, vsi->seid, max_tx_rate);
|
||||
if (ret)
|
||||
goto end_unlock;
|
||||
|
@ -1873,6 +1873,25 @@ static void i40e_del_qch(struct i40e_vf *vf)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_vc_get_max_frame_size
|
||||
* @vf: pointer to the VF
|
||||
*
|
||||
* Max frame size is determined based on the current port's max frame size and
|
||||
* whether a port VLAN is configured on this VF. The VF is not aware whether
|
||||
* it's in a port VLAN so the PF needs to account for this in max frame size
|
||||
* checks and sending the max frame size to the VF.
|
||||
**/
|
||||
static u16 i40e_vc_get_max_frame_size(struct i40e_vf *vf)
|
||||
{
|
||||
u16 max_frame_size = vf->pf->hw.phy.link_info.max_frame_size;
|
||||
|
||||
if (vf->port_vlan_id)
|
||||
max_frame_size -= VLAN_HLEN;
|
||||
|
||||
return max_frame_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_vc_get_vf_resources_msg
|
||||
* @vf: pointer to the VF info
|
||||
@ -1973,6 +1992,7 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg)
|
||||
vfres->max_vectors = pf->hw.func_caps.num_msix_vectors_vf;
|
||||
vfres->rss_key_size = I40E_HKEY_ARRAY_SIZE;
|
||||
vfres->rss_lut_size = I40E_VF_HLUT_ARRAY_SIZE;
|
||||
vfres->max_mtu = i40e_vc_get_max_frame_size(vf);
|
||||
|
||||
if (vf->lan_vsi_idx) {
|
||||
vfres->vsi_res[0].vsi_id = vf->lan_vsi_id;
|
||||
|
@ -114,8 +114,11 @@ u32 iavf_get_tx_pending(struct iavf_ring *ring, bool in_sw)
|
||||
{
|
||||
u32 head, tail;
|
||||
|
||||
/* underlying hardware might not allow access and/or always return
|
||||
* 0 for the head/tail registers so just use the cached values
|
||||
*/
|
||||
head = ring->next_to_clean;
|
||||
tail = readl(ring->tail);
|
||||
tail = ring->next_to_use;
|
||||
|
||||
if (head != tail)
|
||||
return (head < tail) ?
|
||||
@ -1371,7 +1374,7 @@ static struct sk_buff *iavf_build_skb(struct iavf_ring *rx_ring,
|
||||
#endif
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (!rx_buffer)
|
||||
if (!rx_buffer || !size)
|
||||
return NULL;
|
||||
/* prefetch first cache line of first page */
|
||||
va = page_address(rx_buffer->page) + rx_buffer->page_offset;
|
||||
@ -1531,7 +1534,7 @@ static int iavf_clean_rx_irq(struct iavf_ring *rx_ring, int budget)
|
||||
/* exit if we failed to retrieve a buffer */
|
||||
if (!skb) {
|
||||
rx_ring->rx_stats.alloc_buff_failed++;
|
||||
if (rx_buffer)
|
||||
if (rx_buffer && size)
|
||||
rx_buffer->pagecnt_bias++;
|
||||
break;
|
||||
}
|
||||
|
@ -241,11 +241,14 @@ int iavf_get_vf_config(struct iavf_adapter *adapter)
|
||||
void iavf_configure_queues(struct iavf_adapter *adapter)
|
||||
{
|
||||
struct virtchnl_vsi_queue_config_info *vqci;
|
||||
struct virtchnl_queue_pair_info *vqpi;
|
||||
int i, max_frame = adapter->vf_res->max_mtu;
|
||||
int pairs = adapter->num_active_queues;
|
||||
int i, max_frame = IAVF_MAX_RXBUFFER;
|
||||
struct virtchnl_queue_pair_info *vqpi;
|
||||
size_t len;
|
||||
|
||||
if (max_frame > IAVF_MAX_RXBUFFER || !max_frame)
|
||||
max_frame = IAVF_MAX_RXBUFFER;
|
||||
|
||||
if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
|
||||
/* bail because we already have a command pending */
|
||||
dev_err(&adapter->pdev->dev, "Cannot configure queues, command %d pending\n",
|
||||
|
@ -2064,9 +2064,9 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev)
|
||||
|
||||
skb_reserve(copy_skb, 2);
|
||||
skb_put(copy_skb, len);
|
||||
dma_sync_single_for_cpu(hp->dma_dev, dma_addr, len, DMA_FROM_DEVICE);
|
||||
dma_sync_single_for_cpu(hp->dma_dev, dma_addr, len + 2, DMA_FROM_DEVICE);
|
||||
skb_copy_from_linear_data(skb, copy_skb->data, len);
|
||||
dma_sync_single_for_device(hp->dma_dev, dma_addr, len, DMA_FROM_DEVICE);
|
||||
dma_sync_single_for_device(hp->dma_dev, dma_addr, len + 2, DMA_FROM_DEVICE);
|
||||
/* Reuse original ring buffer. */
|
||||
hme_write_rxd(hp, this,
|
||||
(RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)),
|
||||
|
@ -496,7 +496,6 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb)
|
||||
|
||||
static int ipvlan_process_outbound(struct sk_buff *skb)
|
||||
{
|
||||
struct ethhdr *ethh = eth_hdr(skb);
|
||||
int ret = NET_XMIT_DROP;
|
||||
|
||||
/* The ipvlan is a pseudo-L2 device, so the packets that we receive
|
||||
@ -506,6 +505,8 @@ static int ipvlan_process_outbound(struct sk_buff *skb)
|
||||
if (skb_mac_header_was_set(skb)) {
|
||||
/* In this mode we dont care about
|
||||
* multicast and broadcast traffic */
|
||||
struct ethhdr *ethh = eth_hdr(skb);
|
||||
|
||||
if (is_multicast_ether_addr(ethh->h_dest)) {
|
||||
pr_debug_ratelimited(
|
||||
"Dropped {multi|broad}cast of type=[%x]\n",
|
||||
@ -590,7 +591,7 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev)
|
||||
static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
const struct ipvl_dev *ipvlan = netdev_priv(dev);
|
||||
struct ethhdr *eth = eth_hdr(skb);
|
||||
struct ethhdr *eth = skb_eth_hdr(skb);
|
||||
struct ipvl_addr *addr;
|
||||
void *lyr3h;
|
||||
int addr_type;
|
||||
@ -620,6 +621,7 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
|
||||
return dev_forward_skb(ipvlan->phy_dev, skb);
|
||||
|
||||
} else if (is_multicast_ether_addr(eth->h_dest)) {
|
||||
skb_reset_mac_header(skb);
|
||||
ipvlan_skb_crossing_ns(skb, NULL);
|
||||
ipvlan_multicast_enqueue(ipvlan->port, skb, true);
|
||||
return NET_XMIT_SUCCESS;
|
||||
|
@ -1270,10 +1270,12 @@ static int team_port_add(struct team *team, struct net_device *port_dev,
|
||||
}
|
||||
}
|
||||
|
||||
netif_addr_lock_bh(dev);
|
||||
dev_uc_sync_multiple(port_dev, dev);
|
||||
dev_mc_sync_multiple(port_dev, dev);
|
||||
netif_addr_unlock_bh(dev);
|
||||
if (dev->flags & IFF_UP) {
|
||||
netif_addr_lock_bh(dev);
|
||||
dev_uc_sync_multiple(port_dev, dev);
|
||||
dev_mc_sync_multiple(port_dev, dev);
|
||||
netif_addr_unlock_bh(dev);
|
||||
}
|
||||
|
||||
port->index = -1;
|
||||
list_add_tail_rcu(&port->list, &team->port_list);
|
||||
@ -1344,8 +1346,10 @@ static int team_port_del(struct team *team, struct net_device *port_dev)
|
||||
netdev_rx_handler_unregister(port_dev);
|
||||
team_port_disable_netpoll(port);
|
||||
vlan_vids_del_by_dev(port_dev, dev);
|
||||
dev_uc_unsync(port_dev, dev);
|
||||
dev_mc_unsync(port_dev, dev);
|
||||
if (dev->flags & IFF_UP) {
|
||||
dev_uc_unsync(port_dev, dev);
|
||||
dev_mc_unsync(port_dev, dev);
|
||||
}
|
||||
dev_close(port_dev);
|
||||
team_port_leave(team, port);
|
||||
|
||||
@ -1694,6 +1698,14 @@ static int team_open(struct net_device *dev)
|
||||
|
||||
static int team_close(struct net_device *dev)
|
||||
{
|
||||
struct team *team = netdev_priv(dev);
|
||||
struct team_port *port;
|
||||
|
||||
list_for_each_entry(port, &team->port_list, list) {
|
||||
dev_uc_unsync(port->dev, dev);
|
||||
dev_mc_unsync(port->dev, dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1046,6 +1046,7 @@ static const struct usb_device_id products[] = {
|
||||
{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0512)}, /* Quectel EG12/EM12 */
|
||||
{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0620)}, /* Quectel EM160R-GL */
|
||||
{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0800)}, /* Quectel RM500Q-GL */
|
||||
{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0801)}, /* Quectel RM520N */
|
||||
|
||||
/* 3. Combined interface devices matching on interface number */
|
||||
{QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */
|
||||
|
@ -315,7 +315,7 @@ static int unflatten_dt_nodes(const void *blob,
|
||||
for (offset = 0;
|
||||
offset >= 0 && depth >= initial_depth;
|
||||
offset = fdt_next_node(blob, offset, &depth)) {
|
||||
if (WARN_ON_ONCE(depth >= FDT_MAX_DEPTH))
|
||||
if (WARN_ON_ONCE(depth >= FDT_MAX_DEPTH - 1))
|
||||
continue;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_OF_KOBJ) &&
|
||||
|
@ -281,6 +281,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
|
||||
return 0;
|
||||
|
||||
unregister:
|
||||
of_node_put(child);
|
||||
mdiobus_unregister(mdio);
|
||||
return rc;
|
||||
}
|
||||
|
@ -1544,6 +1544,7 @@ static int __init ccio_probe(struct parisc_device *dev)
|
||||
}
|
||||
ccio_ioc_init(ioc);
|
||||
if (ccio_init_resources(ioc)) {
|
||||
iounmap(ioc->ioc_regs);
|
||||
kfree(ioc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -788,7 +788,7 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
|
||||
((pfuze_chip->chip_id == PFUZE3000) ? "3000" : "3001"))));
|
||||
|
||||
memcpy(pfuze_chip->regulator_descs, pfuze_chip->pfuze_regulators,
|
||||
sizeof(pfuze_chip->regulator_descs));
|
||||
regulator_num * sizeof(struct pfuze_regulator));
|
||||
|
||||
ret = pfuze_parse_regulators_dt(pfuze_chip);
|
||||
if (ret)
|
||||
|
@ -675,12 +675,12 @@ int dasd_alias_remove_device(struct dasd_device *device)
|
||||
struct dasd_device *dasd_alias_get_start_dev(struct dasd_device *base_device)
|
||||
{
|
||||
struct dasd_eckd_private *alias_priv, *private = base_device->private;
|
||||
struct alias_pav_group *group = private->pavgroup;
|
||||
struct alias_lcu *lcu = private->lcu;
|
||||
struct dasd_device *alias_device;
|
||||
struct alias_pav_group *group;
|
||||
unsigned long flags;
|
||||
|
||||
if (!group || !lcu)
|
||||
if (!lcu)
|
||||
return NULL;
|
||||
if (lcu->pav == NO_PAV ||
|
||||
lcu->flags & (NEED_UAC_UPDATE | UPDATE_PENDING))
|
||||
@ -697,6 +697,11 @@ struct dasd_device *dasd_alias_get_start_dev(struct dasd_device *base_device)
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&lcu->lock, flags);
|
||||
group = private->pavgroup;
|
||||
if (!group) {
|
||||
spin_unlock_irqrestore(&lcu->lock, flags);
|
||||
return NULL;
|
||||
}
|
||||
alias_device = group->next;
|
||||
if (!alias_device) {
|
||||
if (list_empty(&group->aliaslist)) {
|
||||
|
@ -306,16 +306,16 @@ static int atmel_config_rs485(struct uart_port *port,
|
||||
|
||||
mode = atmel_uart_readl(port, ATMEL_US_MR);
|
||||
|
||||
/* Resetting serial mode to RS232 (0x0) */
|
||||
mode &= ~ATMEL_US_USMODE;
|
||||
|
||||
port->rs485 = *rs485conf;
|
||||
|
||||
if (rs485conf->flags & SER_RS485_ENABLED) {
|
||||
dev_dbg(port->dev, "Setting UART to RS485\n");
|
||||
atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
|
||||
if (rs485conf->flags & SER_RS485_RX_DURING_TX)
|
||||
atmel_port->tx_done_mask = ATMEL_US_TXRDY;
|
||||
else
|
||||
atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
|
||||
|
||||
atmel_uart_writel(port, ATMEL_US_TTGR,
|
||||
rs485conf->delay_rts_after_send);
|
||||
mode &= ~ATMEL_US_USMODE;
|
||||
mode |= ATMEL_US_USMODE_RS485;
|
||||
} else {
|
||||
dev_dbg(port->dev, "Setting UART to RS232\n");
|
||||
@ -832,7 +832,7 @@ static void atmel_tx_chars(struct uart_port *port)
|
||||
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
|
||||
|
||||
if (port->x_char &&
|
||||
(atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
|
||||
(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY)) {
|
||||
atmel_uart_write_char(port, port->x_char);
|
||||
port->icount.tx++;
|
||||
port->x_char = 0;
|
||||
@ -840,8 +840,7 @@ static void atmel_tx_chars(struct uart_port *port)
|
||||
if (uart_circ_empty(xmit) || uart_tx_stopped(port))
|
||||
return;
|
||||
|
||||
while (atmel_uart_readl(port, ATMEL_US_CSR) &
|
||||
atmel_port->tx_done_mask) {
|
||||
while (atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY) {
|
||||
atmel_uart_write_char(port, xmit->buf[xmit->tail]);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
port->icount.tx++;
|
||||
@ -852,10 +851,20 @@ static void atmel_tx_chars(struct uart_port *port)
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(port);
|
||||
|
||||
if (!uart_circ_empty(xmit))
|
||||
if (!uart_circ_empty(xmit)) {
|
||||
/* we still have characters to transmit, so we should continue
|
||||
* transmitting them when TX is ready, regardless of
|
||||
* mode or duplexity
|
||||
*/
|
||||
atmel_port->tx_done_mask |= ATMEL_US_TXRDY;
|
||||
|
||||
/* Enable interrupts */
|
||||
atmel_uart_writel(port, ATMEL_US_IER,
|
||||
atmel_port->tx_done_mask);
|
||||
} else {
|
||||
if (atmel_uart_is_half_duplex(port))
|
||||
atmel_port->tx_done_mask &= ~ATMEL_US_TXRDY;
|
||||
}
|
||||
}
|
||||
|
||||
static void atmel_complete_tx_dma(void *arg)
|
||||
@ -2541,8 +2550,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
|
||||
* Use TXEMPTY for interrupt when rs485 or ISO7816 else TXRDY or
|
||||
* ENDTX|TXBUFE
|
||||
*/
|
||||
if (port->rs485.flags & SER_RS485_ENABLED ||
|
||||
port->iso7816.flags & SER_ISO7816_ENABLED)
|
||||
if (atmel_uart_is_half_duplex(port))
|
||||
atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
|
||||
else if (atmel_use_pdc_tx(port)) {
|
||||
port->fifosize = PDC_BUFFER_SIZE;
|
||||
|
@ -519,7 +519,7 @@ static void tegra_uart_tx_dma_complete(void *args)
|
||||
count = tup->tx_bytes_requested - state.residue;
|
||||
async_tx_ack(tup->tx_dma_desc);
|
||||
spin_lock_irqsave(&tup->uport.lock, flags);
|
||||
xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
|
||||
uart_xmit_advance(&tup->uport, count);
|
||||
tup->tx_in_progress = 0;
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(&tup->uport);
|
||||
@ -606,7 +606,6 @@ static unsigned int tegra_uart_tx_empty(struct uart_port *u)
|
||||
static void tegra_uart_stop_tx(struct uart_port *u)
|
||||
{
|
||||
struct tegra_uart_port *tup = to_tegra_uport(u);
|
||||
struct circ_buf *xmit = &tup->uport.state->xmit;
|
||||
struct dma_tx_state state;
|
||||
unsigned int count;
|
||||
|
||||
@ -617,7 +616,7 @@ static void tegra_uart_stop_tx(struct uart_port *u)
|
||||
dmaengine_tx_status(tup->tx_dma_chan, tup->tx_cookie, &state);
|
||||
count = tup->tx_bytes_requested - state.residue;
|
||||
async_tx_ack(tup->tx_dma_desc);
|
||||
xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
|
||||
uart_xmit_advance(&tup->uport, count);
|
||||
tup->tx_in_progress = 0;
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@ static void tegra_tcu_uart_start_tx(struct uart_port *port)
|
||||
break;
|
||||
|
||||
tegra_tcu_write(tcu, &xmit->buf[xmit->tail], count);
|
||||
xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
|
||||
uart_xmit_advance(port, count);
|
||||
}
|
||||
|
||||
uart_write_wakeup(port);
|
||||
|
@ -1259,6 +1259,7 @@ static int cdns3_check_ep_interrupt_proceed(struct cdns3_endpoint *priv_ep)
|
||||
ep_cfg &= ~EP_CFG_ENABLE;
|
||||
writel(ep_cfg, &priv_dev->regs->ep_cfg);
|
||||
priv_ep->flags &= ~EP_QUIRK_ISO_OUT_EN;
|
||||
priv_ep->flags |= EP_UPDATE_EP_TRBADDR;
|
||||
}
|
||||
cdns3_transfer_completed(priv_dev, priv_ep);
|
||||
} else if (!(priv_ep->flags & EP_STALLED) &&
|
||||
|
@ -227,7 +227,7 @@ u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type)
|
||||
* dwc3_core_soft_reset - Issues core soft reset and PHY reset
|
||||
* @dwc: pointer to our context structure
|
||||
*/
|
||||
static int dwc3_core_soft_reset(struct dwc3 *dwc)
|
||||
int dwc3_core_soft_reset(struct dwc3 *dwc)
|
||||
{
|
||||
u32 reg;
|
||||
int retries = 1000;
|
||||
|
@ -998,6 +998,7 @@ struct dwc3_scratchpad_array {
|
||||
* @tx_max_burst_prd: max periodic ESS transmit burst size
|
||||
* @hsphy_interface: "utmi" or "ulpi"
|
||||
* @connected: true when we're connected to a host, false otherwise
|
||||
* @softconnect: true when gadget connect is called, false when disconnect runs
|
||||
* @delayed_status: true when gadget driver asks for delayed status
|
||||
* @ep0_bounced: true when we used bounce buffer
|
||||
* @ep0_expect_in: true when we expect a DATA IN transfer
|
||||
@ -1202,6 +1203,7 @@ struct dwc3 {
|
||||
const char *hsphy_interface;
|
||||
|
||||
unsigned connected:1;
|
||||
unsigned softconnect:1;
|
||||
unsigned delayed_status:1;
|
||||
unsigned ep0_bounced:1;
|
||||
unsigned ep0_expect_in:1;
|
||||
@ -1426,6 +1428,8 @@ bool dwc3_has_imod(struct dwc3 *dwc);
|
||||
int dwc3_event_buffers_setup(struct dwc3 *dwc);
|
||||
void dwc3_event_buffers_cleanup(struct dwc3 *dwc);
|
||||
|
||||
int dwc3_core_soft_reset(struct dwc3 *dwc);
|
||||
|
||||
#if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
|
||||
int dwc3_host_init(struct dwc3 *dwc);
|
||||
void dwc3_host_exit(struct dwc3 *dwc);
|
||||
|
@ -2008,14 +2008,42 @@ static void dwc3_gadget_disable_irq(struct dwc3 *dwc);
|
||||
static void __dwc3_gadget_stop(struct dwc3 *dwc);
|
||||
static int __dwc3_gadget_start(struct dwc3 *dwc);
|
||||
|
||||
static int dwc3_gadget_soft_disconnect(struct dwc3 *dwc)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
dwc->connected = false;
|
||||
|
||||
/*
|
||||
* In the Synopsys DesignWare Cores USB3 Databook Rev. 3.30a
|
||||
* Section 4.1.8 Table 4-7, it states that for a device-initiated
|
||||
* disconnect, the SW needs to ensure that it sends "a DEPENDXFER
|
||||
* command for any active transfers" before clearing the RunStop
|
||||
* bit.
|
||||
*/
|
||||
dwc3_stop_active_transfers(dwc);
|
||||
__dwc3_gadget_stop(dwc);
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
|
||||
/*
|
||||
* Note: if the GEVNTCOUNT indicates events in the event buffer, the
|
||||
* driver needs to acknowledge them before the controller can halt.
|
||||
* Simply let the interrupt handler acknowledges and handle the
|
||||
* remaining event generated by the controller while polling for
|
||||
* DSTS.DEVCTLHLT.
|
||||
*/
|
||||
return dwc3_gadget_run_stop(dwc, false, false);
|
||||
}
|
||||
|
||||
static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
|
||||
{
|
||||
struct dwc3 *dwc = gadget_to_dwc(g);
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
is_on = !!is_on;
|
||||
|
||||
dwc->softconnect = is_on;
|
||||
/*
|
||||
* Per databook, when we want to stop the gadget, if a control transfer
|
||||
* is still in process, complete it and get the core into setup phase.
|
||||
@ -2051,49 +2079,26 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Synchronize and disable any further event handling while controller
|
||||
* is being enabled/disabled.
|
||||
*/
|
||||
disable_irq(dwc->irq_gadget);
|
||||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
|
||||
if (!is_on) {
|
||||
u32 count;
|
||||
|
||||
dwc->connected = false;
|
||||
/*
|
||||
* In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a
|
||||
* Section 4.1.8 Table 4-7, it states that for a device-initiated
|
||||
* disconnect, the SW needs to ensure that it sends "a DEPENDXFER
|
||||
* command for any active transfers" before clearing the RunStop
|
||||
* bit.
|
||||
*/
|
||||
dwc3_stop_active_transfers(dwc);
|
||||
__dwc3_gadget_stop(dwc);
|
||||
|
||||
/*
|
||||
* In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a
|
||||
* Section 1.3.4, it mentions that for the DEVCTRLHLT bit, the
|
||||
* "software needs to acknowledge the events that are generated
|
||||
* (by writing to GEVNTCOUNTn) while it is waiting for this bit
|
||||
* to be set to '1'."
|
||||
*/
|
||||
count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0));
|
||||
count &= DWC3_GEVNTCOUNT_MASK;
|
||||
if (count > 0) {
|
||||
dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count);
|
||||
dwc->ev_buf->lpos = (dwc->ev_buf->lpos + count) %
|
||||
dwc->ev_buf->length;
|
||||
}
|
||||
} else {
|
||||
__dwc3_gadget_start(dwc);
|
||||
if (dwc->pullups_connected == is_on) {
|
||||
pm_runtime_put(dwc->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = dwc3_gadget_run_stop(dwc, is_on, false);
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
enable_irq(dwc->irq_gadget);
|
||||
if (!is_on) {
|
||||
ret = dwc3_gadget_soft_disconnect(dwc);
|
||||
} else {
|
||||
/*
|
||||
* In the Synopsys DWC_usb31 1.90a programming guide section
|
||||
* 4.1.9, it specifies that for a reconnect after a
|
||||
* device-initiated disconnect requires a core soft reset
|
||||
* (DCTL.CSftRst) before enabling the run/stop bit.
|
||||
*/
|
||||
dwc3_core_soft_reset(dwc);
|
||||
|
||||
dwc3_event_buffers_setup(dwc);
|
||||
__dwc3_gadget_start(dwc);
|
||||
ret = dwc3_gadget_run_stop(dwc, true, false);
|
||||
}
|
||||
|
||||
pm_runtime_put(dwc->dev);
|
||||
|
||||
@ -3791,7 +3796,7 @@ int dwc3_gadget_resume(struct dwc3 *dwc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!dwc->gadget_driver)
|
||||
if (!dwc->gadget_driver || !dwc->softconnect)
|
||||
return 0;
|
||||
|
||||
ret = __dwc3_gadget_start(dwc);
|
||||
|
@ -25,6 +25,13 @@
|
||||
*/
|
||||
#define TT_MICROFRAMES_MAX 9
|
||||
|
||||
/* schedule error type */
|
||||
#define ESCH_SS_Y6 1001
|
||||
#define ESCH_SS_OVERLAP 1002
|
||||
#define ESCH_CS_OVERFLOW 1003
|
||||
#define ESCH_BW_OVERFLOW 1004
|
||||
#define ESCH_FIXME 1005
|
||||
|
||||
/* mtk scheduler bitmasks */
|
||||
#define EP_BPKTS(p) ((p) & 0x7f)
|
||||
#define EP_BCSCOUNT(p) (((p) & 0x7) << 8)
|
||||
@ -32,6 +39,24 @@
|
||||
#define EP_BOFFSET(p) ((p) & 0x3fff)
|
||||
#define EP_BREPEAT(p) (((p) & 0x7fff) << 16)
|
||||
|
||||
static char *sch_error_string(int err_num)
|
||||
{
|
||||
switch (err_num) {
|
||||
case ESCH_SS_Y6:
|
||||
return "Can't schedule Start-Split in Y6";
|
||||
case ESCH_SS_OVERLAP:
|
||||
return "Can't find a suitable Start-Split location";
|
||||
case ESCH_CS_OVERFLOW:
|
||||
return "The last Complete-Split is greater than 7";
|
||||
case ESCH_BW_OVERFLOW:
|
||||
return "Bandwidth exceeds the maximum limit";
|
||||
case ESCH_FIXME:
|
||||
return "FIXME, to be resolved";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static int is_fs_or_ls(enum usb_device_speed speed)
|
||||
{
|
||||
return speed == USB_SPEED_FULL || speed == USB_SPEED_LOW;
|
||||
@ -375,7 +400,6 @@ static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw,
|
||||
sch_ep->bw_budget_table[j];
|
||||
}
|
||||
}
|
||||
sch_ep->allocated = used;
|
||||
}
|
||||
|
||||
static int check_fs_bus_bw(struct mu3h_sch_ep_info *sch_ep, int offset)
|
||||
@ -384,19 +408,20 @@ static int check_fs_bus_bw(struct mu3h_sch_ep_info *sch_ep, int offset)
|
||||
u32 num_esit, tmp;
|
||||
int base;
|
||||
int i, j;
|
||||
u8 uframes = DIV_ROUND_UP(sch_ep->maxpkt, FS_PAYLOAD_MAX);
|
||||
|
||||
num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
|
||||
|
||||
if (sch_ep->ep_type == INT_IN_EP || sch_ep->ep_type == ISOC_IN_EP)
|
||||
offset++;
|
||||
|
||||
for (i = 0; i < num_esit; i++) {
|
||||
base = offset + i * sch_ep->esit;
|
||||
|
||||
/*
|
||||
* Compared with hs bus, no matter what ep type,
|
||||
* the hub will always delay one uframe to send data
|
||||
*/
|
||||
for (j = 0; j < sch_ep->cs_count; j++) {
|
||||
for (j = 0; j < uframes; j++) {
|
||||
tmp = tt->fs_bus_bw[base + j] + sch_ep->bw_cost_per_microframe;
|
||||
if (tmp > FS_PAYLOAD_MAX)
|
||||
return -ERANGE;
|
||||
return -ESCH_BW_OVERFLOW;
|
||||
}
|
||||
}
|
||||
|
||||
@ -406,15 +431,11 @@ static int check_fs_bus_bw(struct mu3h_sch_ep_info *sch_ep, int offset)
|
||||
static int check_sch_tt(struct usb_device *udev,
|
||||
struct mu3h_sch_ep_info *sch_ep, u32 offset)
|
||||
{
|
||||
struct mu3h_sch_tt *tt = sch_ep->sch_tt;
|
||||
u32 extra_cs_count;
|
||||
u32 fs_budget_start;
|
||||
u32 start_ss, last_ss;
|
||||
u32 start_cs, last_cs;
|
||||
int i;
|
||||
|
||||
start_ss = offset % 8;
|
||||
fs_budget_start = (start_ss + 1) % 8;
|
||||
|
||||
if (sch_ep->ep_type == ISOC_OUT_EP) {
|
||||
last_ss = start_ss + sch_ep->cs_count - 1;
|
||||
@ -424,11 +445,7 @@ static int check_sch_tt(struct usb_device *udev,
|
||||
* must never schedule Start-Split in Y6
|
||||
*/
|
||||
if (!(start_ss == 7 || last_ss < 6))
|
||||
return -ERANGE;
|
||||
|
||||
for (i = 0; i < sch_ep->cs_count; i++)
|
||||
if (test_bit(offset + i, tt->ss_bit_map))
|
||||
return -ERANGE;
|
||||
return -ESCH_SS_Y6;
|
||||
|
||||
} else {
|
||||
u32 cs_count = DIV_ROUND_UP(sch_ep->maxpkt, FS_PAYLOAD_MAX);
|
||||
@ -438,29 +455,24 @@ static int check_sch_tt(struct usb_device *udev,
|
||||
* must never schedule Start-Split in Y6
|
||||
*/
|
||||
if (start_ss == 6)
|
||||
return -ERANGE;
|
||||
return -ESCH_SS_Y6;
|
||||
|
||||
/* one uframe for ss + one uframe for idle */
|
||||
start_cs = (start_ss + 2) % 8;
|
||||
last_cs = start_cs + cs_count - 1;
|
||||
|
||||
if (last_cs > 7)
|
||||
return -ERANGE;
|
||||
return -ESCH_CS_OVERFLOW;
|
||||
|
||||
if (sch_ep->ep_type == ISOC_IN_EP)
|
||||
extra_cs_count = (last_cs == 7) ? 1 : 2;
|
||||
else /* ep_type : INTR IN / INTR OUT */
|
||||
extra_cs_count = (fs_budget_start == 6) ? 1 : 2;
|
||||
extra_cs_count = 1;
|
||||
|
||||
cs_count += extra_cs_count;
|
||||
if (cs_count > 7)
|
||||
cs_count = 7; /* HW limit */
|
||||
|
||||
for (i = 0; i < cs_count + 2; i++) {
|
||||
if (test_bit(offset + i, tt->ss_bit_map))
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
sch_ep->cs_count = cs_count;
|
||||
/* one for ss, the other for idle */
|
||||
sch_ep->num_budget_microframes = cs_count + 2;
|
||||
@ -482,28 +494,24 @@ static void update_sch_tt(struct usb_device *udev,
|
||||
struct mu3h_sch_tt *tt = sch_ep->sch_tt;
|
||||
u32 base, num_esit;
|
||||
int bw_updated;
|
||||
int bits;
|
||||
int i, j;
|
||||
int offset = sch_ep->offset;
|
||||
u8 uframes = DIV_ROUND_UP(sch_ep->maxpkt, FS_PAYLOAD_MAX);
|
||||
|
||||
num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
|
||||
bits = (sch_ep->ep_type == ISOC_OUT_EP) ? sch_ep->cs_count : 1;
|
||||
|
||||
if (used)
|
||||
bw_updated = sch_ep->bw_cost_per_microframe;
|
||||
else
|
||||
bw_updated = -sch_ep->bw_cost_per_microframe;
|
||||
|
||||
if (sch_ep->ep_type == INT_IN_EP || sch_ep->ep_type == ISOC_IN_EP)
|
||||
offset++;
|
||||
|
||||
for (i = 0; i < num_esit; i++) {
|
||||
base = sch_ep->offset + i * sch_ep->esit;
|
||||
base = offset + i * sch_ep->esit;
|
||||
|
||||
for (j = 0; j < bits; j++) {
|
||||
if (used)
|
||||
set_bit(base + j, tt->ss_bit_map);
|
||||
else
|
||||
clear_bit(base + j, tt->ss_bit_map);
|
||||
}
|
||||
|
||||
for (j = 0; j < sch_ep->cs_count; j++)
|
||||
for (j = 0; j < uframes; j++)
|
||||
tt->fs_bus_bw[base + j] += bw_updated;
|
||||
}
|
||||
|
||||
@ -513,21 +521,48 @@ static void update_sch_tt(struct usb_device *udev,
|
||||
list_del(&sch_ep->tt_endpoint);
|
||||
}
|
||||
|
||||
static int load_ep_bw(struct usb_device *udev, struct mu3h_sch_bw_info *sch_bw,
|
||||
struct mu3h_sch_ep_info *sch_ep, bool loaded)
|
||||
{
|
||||
if (sch_ep->sch_tt)
|
||||
update_sch_tt(udev, sch_ep, loaded);
|
||||
|
||||
/* update bus bandwidth info */
|
||||
update_bus_bw(sch_bw, sch_ep, loaded);
|
||||
sch_ep->allocated = loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 get_esit_boundary(struct mu3h_sch_ep_info *sch_ep)
|
||||
{
|
||||
u32 boundary = sch_ep->esit;
|
||||
|
||||
if (sch_ep->sch_tt) { /* LS/FS with TT */
|
||||
/*
|
||||
* tune for CS, normally esit >= 8 for FS/LS,
|
||||
* not add one for other types to avoid access array
|
||||
* out of boundary
|
||||
*/
|
||||
if (sch_ep->ep_type == ISOC_OUT_EP && boundary > 1)
|
||||
boundary--;
|
||||
}
|
||||
|
||||
return boundary;
|
||||
}
|
||||
|
||||
static int check_sch_bw(struct usb_device *udev,
|
||||
struct mu3h_sch_bw_info *sch_bw, struct mu3h_sch_ep_info *sch_ep)
|
||||
{
|
||||
u32 offset;
|
||||
u32 esit;
|
||||
u32 min_bw;
|
||||
u32 min_index;
|
||||
u32 worst_bw;
|
||||
u32 bw_boundary;
|
||||
u32 esit_boundary;
|
||||
u32 min_num_budget;
|
||||
u32 min_cs_count;
|
||||
bool tt_offset_ok = false;
|
||||
int ret;
|
||||
|
||||
esit = sch_ep->esit;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* Search through all possible schedule microframes.
|
||||
@ -537,16 +572,15 @@ static int check_sch_bw(struct usb_device *udev,
|
||||
min_index = 0;
|
||||
min_cs_count = sch_ep->cs_count;
|
||||
min_num_budget = sch_ep->num_budget_microframes;
|
||||
for (offset = 0; offset < esit; offset++) {
|
||||
if (is_fs_or_ls(udev->speed)) {
|
||||
esit_boundary = get_esit_boundary(sch_ep);
|
||||
for (offset = 0; offset < sch_ep->esit; offset++) {
|
||||
if (sch_ep->sch_tt) {
|
||||
ret = check_sch_tt(udev, sch_ep, offset);
|
||||
if (ret)
|
||||
continue;
|
||||
else
|
||||
tt_offset_ok = true;
|
||||
}
|
||||
|
||||
if ((offset + sch_ep->num_budget_microframes) > sch_ep->esit)
|
||||
if ((offset + sch_ep->num_budget_microframes) > esit_boundary)
|
||||
break;
|
||||
|
||||
worst_bw = get_max_bw(sch_bw, sch_ep, offset);
|
||||
@ -569,35 +603,21 @@ static int check_sch_bw(struct usb_device *udev,
|
||||
|
||||
/* check bandwidth */
|
||||
if (min_bw > bw_boundary)
|
||||
return -ERANGE;
|
||||
return ret ? ret : -ESCH_BW_OVERFLOW;
|
||||
|
||||
sch_ep->offset = min_index;
|
||||
sch_ep->cs_count = min_cs_count;
|
||||
sch_ep->num_budget_microframes = min_num_budget;
|
||||
|
||||
if (is_fs_or_ls(udev->speed)) {
|
||||
/* all offset for tt is not ok*/
|
||||
if (!tt_offset_ok)
|
||||
return -ERANGE;
|
||||
|
||||
update_sch_tt(udev, sch_ep, 1);
|
||||
}
|
||||
|
||||
/* update bus bandwidth info */
|
||||
update_bus_bw(sch_bw, sch_ep, 1);
|
||||
|
||||
return 0;
|
||||
return load_ep_bw(udev, sch_bw, sch_ep, true);
|
||||
}
|
||||
|
||||
static void destroy_sch_ep(struct usb_device *udev,
|
||||
struct mu3h_sch_bw_info *sch_bw, struct mu3h_sch_ep_info *sch_ep)
|
||||
{
|
||||
/* only release ep bw check passed by check_sch_bw() */
|
||||
if (sch_ep->allocated) {
|
||||
update_bus_bw(sch_bw, sch_ep, 0);
|
||||
if (sch_ep->sch_tt)
|
||||
update_sch_tt(udev, sch_ep, 0);
|
||||
}
|
||||
if (sch_ep->allocated)
|
||||
load_ep_bw(udev, sch_bw, sch_ep, false);
|
||||
|
||||
if (sch_ep->sch_tt)
|
||||
drop_tt(udev);
|
||||
@ -760,7 +780,8 @@ int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
|
||||
|
||||
ret = check_sch_bw(udev, sch_bw, sch_ep);
|
||||
if (ret) {
|
||||
xhci_err(xhci, "Not enough bandwidth!\n");
|
||||
xhci_err(xhci, "Not enough bandwidth! (%s)\n",
|
||||
sch_error_string(-ret));
|
||||
return -ENOSPC;
|
||||
}
|
||||
}
|
||||
|
@ -20,14 +20,12 @@
|
||||
#define XHCI_MTK_MAX_ESIT 64
|
||||
|
||||
/**
|
||||
* @ss_bit_map: used to avoid start split microframes overlay
|
||||
* @fs_bus_bw: array to keep track of bandwidth already used for FS
|
||||
* @ep_list: Endpoints using this TT
|
||||
* @usb_tt: usb TT related
|
||||
* @tt_port: TT port number
|
||||
*/
|
||||
struct mu3h_sch_tt {
|
||||
DECLARE_BITMAP(ss_bit_map, XHCI_MTK_MAX_ESIT);
|
||||
u32 fs_bus_bw[XHCI_MTK_MAX_ESIT];
|
||||
struct list_head ep_list;
|
||||
struct usb_tt *usb_tt;
|
||||
|
@ -256,6 +256,7 @@ static void option_instat_callback(struct urb *urb);
|
||||
#define QUECTEL_PRODUCT_EM060K 0x030b
|
||||
#define QUECTEL_PRODUCT_EM12 0x0512
|
||||
#define QUECTEL_PRODUCT_RM500Q 0x0800
|
||||
#define QUECTEL_PRODUCT_RM520N 0x0801
|
||||
#define QUECTEL_PRODUCT_EC200S_CN 0x6002
|
||||
#define QUECTEL_PRODUCT_EC200T 0x6026
|
||||
#define QUECTEL_PRODUCT_RM500K 0x7001
|
||||
@ -1138,6 +1139,8 @@ static const struct usb_device_id option_ids[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0xff, 0xff),
|
||||
.driver_info = NUMEP2 },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, 0x0203, 0xff), /* BG95-M3 */
|
||||
.driver_info = ZLP },
|
||||
{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96),
|
||||
.driver_info = RSVD(4) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff),
|
||||
@ -1159,6 +1162,9 @@ static const struct usb_device_id option_ids[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0xff, 0x10),
|
||||
.driver_info = ZLP },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0xff, 0x30) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500K, 0xff, 0x00, 0x00) },
|
||||
|
@ -382,7 +382,7 @@ pxa3xx_gcu_write(struct file *file, const char *buff,
|
||||
struct pxa3xx_gcu_batch *buffer;
|
||||
struct pxa3xx_gcu_priv *priv = to_pxa3xx_gcu_priv(file);
|
||||
|
||||
int words = count / 4;
|
||||
size_t words = count / 4;
|
||||
|
||||
/* Does not need to be atomic. There's a lock in user space,
|
||||
* but anyhow, this is just for statistics. */
|
||||
|
@ -69,6 +69,7 @@ int afs_abort_to_error(u32 abort_code)
|
||||
/* Unified AFS error table */
|
||||
case UAEPERM: return -EPERM;
|
||||
case UAENOENT: return -ENOENT;
|
||||
case UAEAGAIN: return -EAGAIN;
|
||||
case UAEACCES: return -EACCES;
|
||||
case UAEBUSY: return -EBUSY;
|
||||
case UAEEXIST: return -EEXIST;
|
||||
|
@ -791,9 +791,6 @@ cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
|
||||
int length = 0;
|
||||
int total_read;
|
||||
|
||||
smb_msg->msg_control = NULL;
|
||||
smb_msg->msg_controllen = 0;
|
||||
|
||||
for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
|
||||
try_to_freeze();
|
||||
|
||||
@ -844,7 +841,7 @@ int
|
||||
cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
|
||||
unsigned int to_read)
|
||||
{
|
||||
struct msghdr smb_msg;
|
||||
struct msghdr smb_msg = {};
|
||||
struct kvec iov = {.iov_base = buf, .iov_len = to_read};
|
||||
iov_iter_kvec(&smb_msg.msg_iter, READ, &iov, 1, to_read);
|
||||
|
||||
@ -855,7 +852,7 @@ int
|
||||
cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
|
||||
unsigned int page_offset, unsigned int to_read)
|
||||
{
|
||||
struct msghdr smb_msg;
|
||||
struct msghdr smb_msg = {};
|
||||
struct bio_vec bv = {
|
||||
.bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
|
||||
iov_iter_bvec(&smb_msg.msg_iter, READ, &bv, 1, to_read);
|
||||
|
@ -3194,6 +3194,9 @@ static ssize_t __cifs_writev(
|
||||
|
||||
ssize_t cifs_direct_writev(struct kiocb *iocb, struct iov_iter *from)
|
||||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
|
||||
cifs_revalidate_mapping(file->f_inode);
|
||||
return __cifs_writev(iocb, from, true);
|
||||
}
|
||||
|
||||
|
@ -209,10 +209,6 @@ smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
|
||||
|
||||
*sent = 0;
|
||||
|
||||
smb_msg->msg_name = (struct sockaddr *) &server->dstaddr;
|
||||
smb_msg->msg_namelen = sizeof(struct sockaddr);
|
||||
smb_msg->msg_control = NULL;
|
||||
smb_msg->msg_controllen = 0;
|
||||
if (server->noblocksnd)
|
||||
smb_msg->msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
|
||||
else
|
||||
@ -324,7 +320,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
|
||||
sigset_t mask, oldmask;
|
||||
size_t total_len = 0, sent, size;
|
||||
struct socket *ssocket = server->ssocket;
|
||||
struct msghdr smb_msg;
|
||||
struct msghdr smb_msg = {};
|
||||
int val = 1;
|
||||
__be32 rfc1002_marker;
|
||||
|
||||
|
@ -500,6 +500,10 @@ static int __ext4_ext_check(const char *function, unsigned int line,
|
||||
error_msg = "invalid eh_entries";
|
||||
goto corrupted;
|
||||
}
|
||||
if (unlikely((eh->eh_entries == 0) && (depth > 0))) {
|
||||
error_msg = "eh_entries is 0 but eh_depth is > 0";
|
||||
goto corrupted;
|
||||
}
|
||||
if (!ext4_valid_extent_entries(inode, eh, lblk, &pblk, depth)) {
|
||||
error_msg = "invalid extent entries";
|
||||
goto corrupted;
|
||||
|
@ -500,7 +500,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
max_dirs = ndirs / ngroups + inodes_per_group / 16;
|
||||
max_dirs = ndirs / ngroups + inodes_per_group*flex_size / 16;
|
||||
min_inodes = avefreei - inodes_per_group*flex_size / 4;
|
||||
if (min_inodes < 1)
|
||||
min_inodes = 1;
|
||||
|
@ -2375,22 +2375,31 @@ void nfs_fill_super(struct super_block *sb, struct nfs_mount_info *mount_info)
|
||||
if (data && data->bsize)
|
||||
sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits);
|
||||
|
||||
if (server->nfs_client->rpc_ops->version != 2) {
|
||||
/* The VFS shouldn't apply the umask to mode bits. We will do
|
||||
* so ourselves when necessary.
|
||||
switch (server->nfs_client->rpc_ops->version) {
|
||||
case 2:
|
||||
sb->s_time_gran = 1000;
|
||||
sb->s_time_min = 0;
|
||||
sb->s_time_max = U32_MAX;
|
||||
break;
|
||||
case 3:
|
||||
/*
|
||||
* The VFS shouldn't apply the umask to mode bits.
|
||||
* We will do so ourselves when necessary.
|
||||
*/
|
||||
sb->s_flags |= SB_POSIXACL;
|
||||
sb->s_time_gran = 1;
|
||||
sb->s_export_op = &nfs_export_ops;
|
||||
} else
|
||||
sb->s_time_gran = 1000;
|
||||
|
||||
if (server->nfs_client->rpc_ops->version != 4) {
|
||||
sb->s_time_min = 0;
|
||||
sb->s_time_max = U32_MAX;
|
||||
} else {
|
||||
sb->s_export_op = &nfs_export_ops;
|
||||
break;
|
||||
case 4:
|
||||
sb->s_flags |= SB_POSIXACL;
|
||||
sb->s_time_gran = 1;
|
||||
sb->s_time_min = S64_MIN;
|
||||
sb->s_time_max = S64_MAX;
|
||||
if (server->caps & NFS_CAP_ATOMIC_OPEN_V1)
|
||||
sb->s_export_op = &nfs_export_ops;
|
||||
break;
|
||||
}
|
||||
|
||||
nfs_initialise_sb(sb);
|
||||
|
@ -684,8 +684,10 @@ xfs_alloc_update_counters(
|
||||
|
||||
xfs_trans_agblocks_delta(tp, len);
|
||||
if (unlikely(be32_to_cpu(agf->agf_freeblks) >
|
||||
be32_to_cpu(agf->agf_length)))
|
||||
be32_to_cpu(agf->agf_length))) {
|
||||
xfs_buf_corruption_error(agbp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS);
|
||||
return 0;
|
||||
@ -751,6 +753,7 @@ xfs_alloc_ag_vextent_small(
|
||||
|
||||
bp = xfs_btree_get_bufs(args->mp, args->tp, args->agno, fbno);
|
||||
if (!bp) {
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, args->mp);
|
||||
error = -EFSCORRUPTED;
|
||||
goto error;
|
||||
}
|
||||
@ -1995,24 +1998,32 @@ xfs_alloc_longest_free_extent(
|
||||
return pag->pagf_flcount > 0 || pag->pagf_longest > 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the minimum length of the AGFL in the given AG. If @pag is NULL,
|
||||
* return the largest possible minimum length.
|
||||
*/
|
||||
unsigned int
|
||||
xfs_alloc_min_freelist(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_perag *pag)
|
||||
{
|
||||
/* AG btrees have at least 1 level. */
|
||||
static const uint8_t fake_levels[XFS_BTNUM_AGF] = {1, 1, 1};
|
||||
const uint8_t *levels = pag ? pag->pagf_levels : fake_levels;
|
||||
unsigned int min_free;
|
||||
|
||||
ASSERT(mp->m_ag_maxlevels > 0);
|
||||
|
||||
/* space needed by-bno freespace btree */
|
||||
min_free = min_t(unsigned int, pag->pagf_levels[XFS_BTNUM_BNOi] + 1,
|
||||
min_free = min_t(unsigned int, levels[XFS_BTNUM_BNOi] + 1,
|
||||
mp->m_ag_maxlevels);
|
||||
/* space needed by-size freespace btree */
|
||||
min_free += min_t(unsigned int, pag->pagf_levels[XFS_BTNUM_CNTi] + 1,
|
||||
min_free += min_t(unsigned int, levels[XFS_BTNUM_CNTi] + 1,
|
||||
mp->m_ag_maxlevels);
|
||||
/* space needed reverse mapping used space btree */
|
||||
if (xfs_sb_version_hasrmapbt(&mp->m_sb))
|
||||
min_free += min_t(unsigned int,
|
||||
pag->pagf_levels[XFS_BTNUM_RMAPi] + 1,
|
||||
mp->m_rmap_maxlevels);
|
||||
min_free += min_t(unsigned int, levels[XFS_BTNUM_RMAPi] + 1,
|
||||
mp->m_rmap_maxlevels);
|
||||
|
||||
return min_free;
|
||||
}
|
||||
@ -2087,8 +2098,10 @@ xfs_free_agfl_block(
|
||||
return error;
|
||||
|
||||
bp = xfs_btree_get_bufs(tp->t_mountp, tp, agno, agbno);
|
||||
if (!bp)
|
||||
if (!bp) {
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, tp->t_mountp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
xfs_trans_binval(tp, bp);
|
||||
|
||||
return 0;
|
||||
|
@ -2287,8 +2287,10 @@ xfs_attr3_leaf_lookup_int(
|
||||
leaf = bp->b_addr;
|
||||
xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
|
||||
entries = xfs_attr3_leaf_entryp(leaf);
|
||||
if (ichdr.count >= args->geo->blksize / 8)
|
||||
if (ichdr.count >= args->geo->blksize / 8) {
|
||||
xfs_buf_corruption_error(bp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Binary search. (note: small blocks will skip this loop)
|
||||
@ -2304,10 +2306,14 @@ xfs_attr3_leaf_lookup_int(
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (!(probe >= 0 && (!ichdr.count || probe < ichdr.count)))
|
||||
if (!(probe >= 0 && (!ichdr.count || probe < ichdr.count))) {
|
||||
xfs_buf_corruption_error(bp);
|
||||
return -EFSCORRUPTED;
|
||||
if (!(span <= 4 || be32_to_cpu(entry->hashval) == hashval))
|
||||
}
|
||||
if (!(span <= 4 || be32_to_cpu(entry->hashval) == hashval)) {
|
||||
xfs_buf_corruption_error(bp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since we may have duplicate hashval's, find the first matching
|
||||
|
@ -729,6 +729,7 @@ xfs_bmap_extents_to_btree(
|
||||
xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, 1L);
|
||||
abp = xfs_btree_get_bufl(mp, tp, args.fsbno);
|
||||
if (!abp) {
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
|
||||
error = -EFSCORRUPTED;
|
||||
goto out_unreserve_dquot;
|
||||
}
|
||||
@ -1084,6 +1085,7 @@ xfs_bmap_add_attrfork(
|
||||
if (XFS_IFORK_Q(ip))
|
||||
goto trans_cancel;
|
||||
if (ip->i_d.di_anextents != 0) {
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
|
||||
error = -EFSCORRUPTED;
|
||||
goto trans_cancel;
|
||||
}
|
||||
@ -1374,7 +1376,8 @@ xfs_bmap_last_before(
|
||||
case XFS_DINODE_FMT_EXTENTS:
|
||||
break;
|
||||
default:
|
||||
return -EIO;
|
||||
ASSERT(0);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
if (!(ifp->if_flags & XFS_IFEXTENTS)) {
|
||||
@ -1474,8 +1477,10 @@ xfs_bmap_last_offset(
|
||||
return 0;
|
||||
|
||||
if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
|
||||
XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
|
||||
return -EIO;
|
||||
XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS) {
|
||||
ASSERT(0);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
error = xfs_bmap_last_extent(NULL, ip, whichfork, &rec, &is_empty);
|
||||
if (error || is_empty)
|
||||
@ -5871,8 +5876,9 @@ xfs_bmap_insert_extents(
|
||||
XFS_WANT_CORRUPTED_GOTO(mp, !isnullstartblock(got.br_startblock),
|
||||
del_cursor);
|
||||
|
||||
if (stop_fsb >= got.br_startoff + got.br_blockcount) {
|
||||
error = -EIO;
|
||||
if (stop_fsb > got.br_startoff) {
|
||||
ASSERT(0);
|
||||
error = -EFSCORRUPTED;
|
||||
goto del_cursor;
|
||||
}
|
||||
|
||||
|
@ -1820,6 +1820,7 @@ xfs_btree_lookup_get_block(
|
||||
|
||||
out_bad:
|
||||
*blkp = NULL;
|
||||
xfs_buf_corruption_error(bp);
|
||||
xfs_trans_brelse(cur->bc_tp, bp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
@ -1867,8 +1868,10 @@ xfs_btree_lookup(
|
||||
XFS_BTREE_STATS_INC(cur, lookup);
|
||||
|
||||
/* No such thing as a zero-level tree. */
|
||||
if (cur->bc_nlevels == 0)
|
||||
if (cur->bc_nlevels == 0) {
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, cur->bc_mp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
block = NULL;
|
||||
keyno = 0;
|
||||
|
@ -504,6 +504,7 @@ xfs_da3_split(
|
||||
node = oldblk->bp->b_addr;
|
||||
if (node->hdr.info.forw) {
|
||||
if (be32_to_cpu(node->hdr.info.forw) != addblk->blkno) {
|
||||
xfs_buf_corruption_error(oldblk->bp);
|
||||
error = -EFSCORRUPTED;
|
||||
goto out;
|
||||
}
|
||||
@ -516,6 +517,7 @@ xfs_da3_split(
|
||||
node = oldblk->bp->b_addr;
|
||||
if (node->hdr.info.back) {
|
||||
if (be32_to_cpu(node->hdr.info.back) != addblk->blkno) {
|
||||
xfs_buf_corruption_error(oldblk->bp);
|
||||
error = -EFSCORRUPTED;
|
||||
goto out;
|
||||
}
|
||||
@ -1541,8 +1543,10 @@ xfs_da3_node_lookup_int(
|
||||
break;
|
||||
}
|
||||
|
||||
if (magic != XFS_DA_NODE_MAGIC && magic != XFS_DA3_NODE_MAGIC)
|
||||
if (magic != XFS_DA_NODE_MAGIC && magic != XFS_DA3_NODE_MAGIC) {
|
||||
xfs_buf_corruption_error(blk->bp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
blk->magic = XFS_DA_NODE_MAGIC;
|
||||
|
||||
@ -1554,15 +1558,18 @@ xfs_da3_node_lookup_int(
|
||||
btree = dp->d_ops->node_tree_p(node);
|
||||
|
||||
/* Tree taller than we can handle; bail out! */
|
||||
if (nodehdr.level >= XFS_DA_NODE_MAXDEPTH)
|
||||
if (nodehdr.level >= XFS_DA_NODE_MAXDEPTH) {
|
||||
xfs_buf_corruption_error(blk->bp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
/* Check the level from the root. */
|
||||
if (blkno == args->geo->leafblk)
|
||||
expected_level = nodehdr.level - 1;
|
||||
else if (expected_level != nodehdr.level)
|
||||
else if (expected_level != nodehdr.level) {
|
||||
xfs_buf_corruption_error(blk->bp);
|
||||
return -EFSCORRUPTED;
|
||||
else
|
||||
} else
|
||||
expected_level--;
|
||||
|
||||
max = nodehdr.count;
|
||||
@ -1612,12 +1619,17 @@ xfs_da3_node_lookup_int(
|
||||
}
|
||||
|
||||
/* We can't point back to the root. */
|
||||
if (blkno == args->geo->leafblk)
|
||||
if (blkno == args->geo->leafblk) {
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW,
|
||||
dp->i_mount);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
}
|
||||
|
||||
if (expected_level != 0)
|
||||
if (expected_level != 0) {
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, dp->i_mount);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* A leaf block that ends in the hashval that we are interested in
|
||||
|
@ -600,8 +600,10 @@ xfs_dir2_isblock(
|
||||
if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK)))
|
||||
return rval;
|
||||
rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize;
|
||||
if (rval != 0 && args->dp->i_d.di_size != args->geo->blksize)
|
||||
if (rval != 0 && args->dp->i_d.di_size != args->geo->blksize) {
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, args->dp->i_mount);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
*vp = rval;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1343,8 +1343,10 @@ xfs_dir2_leaf_removename(
|
||||
oldbest = be16_to_cpu(bf[0].length);
|
||||
ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
|
||||
bestsp = xfs_dir2_leaf_bests_p(ltp);
|
||||
if (be16_to_cpu(bestsp[db]) != oldbest)
|
||||
if (be16_to_cpu(bestsp[db]) != oldbest) {
|
||||
xfs_buf_corruption_error(lbp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
/*
|
||||
* Mark the former data entry unused.
|
||||
*/
|
||||
|
@ -374,8 +374,10 @@ xfs_dir2_leaf_to_node(
|
||||
leaf = lbp->b_addr;
|
||||
ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
|
||||
if (be32_to_cpu(ltp->bestcount) >
|
||||
(uint)dp->i_d.di_size / args->geo->blksize)
|
||||
(uint)dp->i_d.di_size / args->geo->blksize) {
|
||||
xfs_buf_corruption_error(lbp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy freespace entries from the leaf block to the new block.
|
||||
@ -446,8 +448,10 @@ xfs_dir2_leafn_add(
|
||||
* Quick check just to make sure we are not going to index
|
||||
* into other peoples memory
|
||||
*/
|
||||
if (index < 0)
|
||||
if (index < 0) {
|
||||
xfs_buf_corruption_error(bp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there are already the maximum number of leaf entries in
|
||||
@ -740,8 +744,10 @@ xfs_dir2_leafn_lookup_for_entry(
|
||||
ents = dp->d_ops->leaf_ents_p(leaf);
|
||||
|
||||
xfs_dir3_leaf_check(dp, bp);
|
||||
if (leafhdr.count <= 0)
|
||||
if (leafhdr.count <= 0) {
|
||||
xfs_buf_corruption_error(bp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up the hash value in the leaf entries.
|
||||
|
@ -944,6 +944,27 @@ xfs_dir2_sf_removename(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether the sf dir replace operation need more blocks.
|
||||
*/
|
||||
static bool
|
||||
xfs_dir2_sf_replace_needblock(
|
||||
struct xfs_inode *dp,
|
||||
xfs_ino_t inum)
|
||||
{
|
||||
int newsize;
|
||||
struct xfs_dir2_sf_hdr *sfp;
|
||||
|
||||
if (dp->i_d.di_format != XFS_DINODE_FMT_LOCAL)
|
||||
return false;
|
||||
|
||||
sfp = (struct xfs_dir2_sf_hdr *)dp->i_df.if_u1.if_data;
|
||||
newsize = dp->i_df.if_bytes + (sfp->count + 1) * XFS_INO64_DIFF;
|
||||
|
||||
return inum > XFS_DIR2_MAX_SHORT_INUM &&
|
||||
sfp->i8count == 0 && newsize > XFS_IFORK_DSIZE(dp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Replace the inode number of an entry in a shortform directory.
|
||||
*/
|
||||
@ -980,17 +1001,14 @@ xfs_dir2_sf_replace(
|
||||
*/
|
||||
if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && sfp->i8count == 0) {
|
||||
int error; /* error return value */
|
||||
int newsize; /* new inode size */
|
||||
|
||||
newsize = dp->i_df.if_bytes + (sfp->count + 1) * XFS_INO64_DIFF;
|
||||
/*
|
||||
* Won't fit as shortform, convert to block then do replace.
|
||||
*/
|
||||
if (newsize > XFS_IFORK_DSIZE(dp)) {
|
||||
if (xfs_dir2_sf_replace_needblock(dp, args->inumber)) {
|
||||
error = xfs_dir2_sf_to_block(args);
|
||||
if (error) {
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
return xfs_dir2_block_replace(args);
|
||||
}
|
||||
/*
|
||||
|
@ -2854,3 +2854,67 @@ xfs_ialloc_setup_geometry(
|
||||
else
|
||||
igeo->ialloc_align = 0;
|
||||
}
|
||||
|
||||
/* Compute the location of the root directory inode that is laid out by mkfs. */
|
||||
xfs_ino_t
|
||||
xfs_ialloc_calc_rootino(
|
||||
struct xfs_mount *mp,
|
||||
int sunit)
|
||||
{
|
||||
struct xfs_ino_geometry *igeo = M_IGEO(mp);
|
||||
xfs_agblock_t first_bno;
|
||||
|
||||
/*
|
||||
* Pre-calculate the geometry of AG 0. We know what it looks like
|
||||
* because libxfs knows how to create allocation groups now.
|
||||
*
|
||||
* first_bno is the first block in which mkfs could possibly have
|
||||
* allocated the root directory inode, once we factor in the metadata
|
||||
* that mkfs formats before it. Namely, the four AG headers...
|
||||
*/
|
||||
first_bno = howmany(4 * mp->m_sb.sb_sectsize, mp->m_sb.sb_blocksize);
|
||||
|
||||
/* ...the two free space btree roots... */
|
||||
first_bno += 2;
|
||||
|
||||
/* ...the inode btree root... */
|
||||
first_bno += 1;
|
||||
|
||||
/* ...the initial AGFL... */
|
||||
first_bno += xfs_alloc_min_freelist(mp, NULL);
|
||||
|
||||
/* ...the free inode btree root... */
|
||||
if (xfs_sb_version_hasfinobt(&mp->m_sb))
|
||||
first_bno++;
|
||||
|
||||
/* ...the reverse mapping btree root... */
|
||||
if (xfs_sb_version_hasrmapbt(&mp->m_sb))
|
||||
first_bno++;
|
||||
|
||||
/* ...the reference count btree... */
|
||||
if (xfs_sb_version_hasreflink(&mp->m_sb))
|
||||
first_bno++;
|
||||
|
||||
/*
|
||||
* ...and the log, if it is allocated in the first allocation group.
|
||||
*
|
||||
* This can happen with filesystems that only have a single
|
||||
* allocation group, or very odd geometries created by old mkfs
|
||||
* versions on very small filesystems.
|
||||
*/
|
||||
if (mp->m_sb.sb_logstart &&
|
||||
XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart) == 0)
|
||||
first_bno += mp->m_sb.sb_logblocks;
|
||||
|
||||
/*
|
||||
* Now round first_bno up to whatever allocation alignment is given
|
||||
* by the filesystem or was passed in.
|
||||
*/
|
||||
if (xfs_sb_version_hasdalign(&mp->m_sb) && igeo->ialloc_align > 0)
|
||||
first_bno = roundup(first_bno, sunit);
|
||||
else if (xfs_sb_version_hasalign(&mp->m_sb) &&
|
||||
mp->m_sb.sb_inoalignmt > 1)
|
||||
first_bno = roundup(first_bno, mp->m_sb.sb_inoalignmt);
|
||||
|
||||
return XFS_AGINO_TO_INO(mp, 0, XFS_AGB_TO_AGINO(mp, first_bno));
|
||||
}
|
||||
|
@ -152,5 +152,6 @@ int xfs_inobt_insert_rec(struct xfs_btree_cur *cur, uint16_t holemask,
|
||||
|
||||
int xfs_ialloc_cluster_alignment(struct xfs_mount *mp);
|
||||
void xfs_ialloc_setup_geometry(struct xfs_mount *mp);
|
||||
xfs_ino_t xfs_ialloc_calc_rootino(struct xfs_mount *mp, int sunit);
|
||||
|
||||
#endif /* __XFS_IALLOC_H__ */
|
||||
|
@ -75,11 +75,15 @@ xfs_iformat_fork(
|
||||
error = xfs_iformat_btree(ip, dip, XFS_DATA_FORK);
|
||||
break;
|
||||
default:
|
||||
xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__,
|
||||
dip, sizeof(*dip), __this_address);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip,
|
||||
sizeof(*dip), __this_address);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
if (error)
|
||||
@ -110,6 +114,8 @@ xfs_iformat_fork(
|
||||
error = xfs_iformat_btree(ip, dip, XFS_ATTR_FORK);
|
||||
break;
|
||||
default:
|
||||
xfs_inode_verifier_error(ip, error, __func__, dip,
|
||||
sizeof(*dip), __this_address);
|
||||
error = -EFSCORRUPTED;
|
||||
break;
|
||||
}
|
||||
|
@ -1591,8 +1591,10 @@ xfs_refcount_recover_extent(
|
||||
struct list_head *debris = priv;
|
||||
struct xfs_refcount_recovery *rr;
|
||||
|
||||
if (be32_to_cpu(rec->refc.rc_refcount) != 1)
|
||||
if (be32_to_cpu(rec->refc.rc_refcount) != 1) {
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, cur->bc_mp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
rr = kmem_alloc(sizeof(struct xfs_refcount_recovery), 0);
|
||||
xfs_refcount_btrec_to_irec(rec, &rr->rr_rrec);
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include "xfs_bmap.h"
|
||||
#include "xfs_trans.h"
|
||||
#include "xfs_rtalloc.h"
|
||||
|
||||
#include "xfs_error.h"
|
||||
|
||||
/*
|
||||
* Realtime allocator bitmap functions shared with userspace.
|
||||
@ -70,8 +70,10 @@ xfs_rtbuf_get(
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (nmap == 0 || !xfs_bmap_is_real_extent(&map))
|
||||
if (nmap == 0 || !xfs_bmap_is_real_extent(&map)) {
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
ASSERT(map.br_startblock != NULLFSBLOCK);
|
||||
error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "xfs_inode.h"
|
||||
#include "xfs_attr.h"
|
||||
#include "xfs_trace.h"
|
||||
#include "xfs_error.h"
|
||||
#include <linux/posix_acl_xattr.h>
|
||||
|
||||
|
||||
@ -23,6 +24,7 @@
|
||||
|
||||
STATIC struct posix_acl *
|
||||
xfs_acl_from_disk(
|
||||
struct xfs_mount *mp,
|
||||
const struct xfs_acl *aclp,
|
||||
int len,
|
||||
int max_entries)
|
||||
@ -32,11 +34,18 @@ xfs_acl_from_disk(
|
||||
const struct xfs_acl_entry *ace;
|
||||
unsigned int count, i;
|
||||
|
||||
if (len < sizeof(*aclp))
|
||||
if (len < sizeof(*aclp)) {
|
||||
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, aclp,
|
||||
len);
|
||||
return ERR_PTR(-EFSCORRUPTED);
|
||||
}
|
||||
|
||||
count = be32_to_cpu(aclp->acl_cnt);
|
||||
if (count > max_entries || XFS_ACL_SIZE(count) != len)
|
||||
if (count > max_entries || XFS_ACL_SIZE(count) != len) {
|
||||
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, aclp,
|
||||
len);
|
||||
return ERR_PTR(-EFSCORRUPTED);
|
||||
}
|
||||
|
||||
acl = posix_acl_alloc(count, GFP_KERNEL);
|
||||
if (!acl)
|
||||
@ -145,7 +154,7 @@ xfs_get_acl(struct inode *inode, int type)
|
||||
if (error != -ENOATTR)
|
||||
acl = ERR_PTR(error);
|
||||
} else {
|
||||
acl = xfs_acl_from_disk(xfs_acl, len,
|
||||
acl = xfs_acl_from_disk(ip->i_mount, xfs_acl, len,
|
||||
XFS_ACL_MAX_ENTRIES(ip->i_mount));
|
||||
kmem_free(xfs_acl);
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "xfs_attr_leaf.h"
|
||||
#include "xfs_quota.h"
|
||||
#include "xfs_dir2.h"
|
||||
#include "xfs_error.h"
|
||||
|
||||
/*
|
||||
* Look at all the extents for this logical region,
|
||||
@ -208,8 +209,9 @@ xfs_attr3_node_inactive(
|
||||
* Since this code is recursive (gasp!) we must protect ourselves.
|
||||
*/
|
||||
if (level > XFS_DA_NODE_MAXDEPTH) {
|
||||
xfs_buf_corruption_error(bp);
|
||||
xfs_trans_brelse(*trans, bp); /* no locks for later trans */
|
||||
return -EIO;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
node = bp->b_addr;
|
||||
@ -258,8 +260,9 @@ xfs_attr3_node_inactive(
|
||||
error = xfs_attr3_leaf_inactive(trans, dp, child_bp);
|
||||
break;
|
||||
default:
|
||||
error = -EIO;
|
||||
xfs_buf_corruption_error(child_bp);
|
||||
xfs_trans_brelse(*trans, child_bp);
|
||||
error = -EFSCORRUPTED;
|
||||
break;
|
||||
}
|
||||
if (error)
|
||||
@ -341,7 +344,8 @@ xfs_attr3_root_inactive(
|
||||
error = xfs_attr3_leaf_inactive(trans, dp, bp);
|
||||
break;
|
||||
default:
|
||||
error = -EIO;
|
||||
error = -EFSCORRUPTED;
|
||||
xfs_buf_corruption_error(bp);
|
||||
xfs_trans_brelse(*trans, bp);
|
||||
break;
|
||||
}
|
||||
|
@ -258,8 +258,10 @@ xfs_attr_node_list_lookup(
|
||||
return 0;
|
||||
|
||||
/* We can't point back to the root. */
|
||||
if (cursor->blkno == 0)
|
||||
if (cursor->blkno == 0) {
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
}
|
||||
|
||||
if (expected_level != 0)
|
||||
@ -269,6 +271,7 @@ xfs_attr_node_list_lookup(
|
||||
return 0;
|
||||
|
||||
out_corruptbuf:
|
||||
xfs_buf_corruption_error(bp);
|
||||
xfs_trans_brelse(tp, bp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "xfs_icache.h"
|
||||
#include "xfs_bmap_btree.h"
|
||||
#include "xfs_trans_space.h"
|
||||
|
||||
#include "xfs_error.h"
|
||||
|
||||
kmem_zone_t *xfs_bui_zone;
|
||||
kmem_zone_t *xfs_bud_zone;
|
||||
@ -456,7 +456,7 @@ xfs_bui_recover(
|
||||
if (buip->bui_format.bui_nextents != XFS_BUI_MAX_FAST_EXTENTS) {
|
||||
set_bit(XFS_BUI_RECOVERED, &buip->bui_flags);
|
||||
xfs_bui_release(buip);
|
||||
return -EIO;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -490,7 +490,7 @@ xfs_bui_recover(
|
||||
*/
|
||||
set_bit(XFS_BUI_RECOVERED, &buip->bui_flags);
|
||||
xfs_bui_release(buip);
|
||||
return -EIO;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
|
||||
@ -525,6 +525,7 @@ xfs_bui_recover(
|
||||
type = bui_type;
|
||||
break;
|
||||
default:
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
|
||||
error = -EFSCORRUPTED;
|
||||
goto err_inode;
|
||||
}
|
||||
|
@ -1167,6 +1167,7 @@ xfs_prepare_shift(
|
||||
struct xfs_inode *ip,
|
||||
loff_t offset)
|
||||
{
|
||||
struct xfs_mount *mp = ip->i_mount;
|
||||
int error;
|
||||
|
||||
/*
|
||||
@ -1179,6 +1180,17 @@ xfs_prepare_shift(
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Shift operations must stabilize the start block offset boundary along
|
||||
* with the full range of the operation. If we don't, a COW writeback
|
||||
* completion could race with an insert, front merge with the start
|
||||
* extent (after split) during the shift and corrupt the file. Start
|
||||
* with the block just prior to the start to stabilize the boundary.
|
||||
*/
|
||||
offset = round_down(offset, 1 << mp->m_sb.sb_blocklog);
|
||||
if (offset)
|
||||
offset -= (1 << mp->m_sb.sb_blocklog);
|
||||
|
||||
/*
|
||||
* Writeback and invalidate cache for the remainder of the file as we're
|
||||
* about to shift down every extent from offset to EOF.
|
||||
|
@ -956,7 +956,7 @@ xfs_buf_item_relse(
|
||||
struct xfs_buf_log_item *bip = bp->b_log_item;
|
||||
|
||||
trace_xfs_buf_item_relse(bp, _RET_IP_);
|
||||
ASSERT(!(bip->bli_item.li_flags & XFS_LI_IN_AIL));
|
||||
ASSERT(!test_bit(XFS_LI_IN_AIL, &bip->bli_item.li_flags));
|
||||
|
||||
bp->b_log_item = NULL;
|
||||
if (list_empty(&bp->b_li_list))
|
||||
|
@ -1125,7 +1125,7 @@ xfs_qm_dqflush(
|
||||
xfs_buf_relse(bp);
|
||||
xfs_dqfunlock(dqp);
|
||||
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
|
||||
return -EIO;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
/* This is the only portion of data that needs to persist */
|
||||
|
@ -329,7 +329,7 @@ xfs_corruption_error(
|
||||
const char *tag,
|
||||
int level,
|
||||
struct xfs_mount *mp,
|
||||
void *buf,
|
||||
const void *buf,
|
||||
size_t bufsize,
|
||||
const char *filename,
|
||||
int linenum,
|
||||
@ -341,6 +341,27 @@ xfs_corruption_error(
|
||||
xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair");
|
||||
}
|
||||
|
||||
/*
|
||||
* Complain about the kinds of metadata corruption that we can't detect from a
|
||||
* verifier, such as incorrect inter-block relationship data. Does not set
|
||||
* bp->b_error.
|
||||
*/
|
||||
void
|
||||
xfs_buf_corruption_error(
|
||||
struct xfs_buf *bp)
|
||||
{
|
||||
struct xfs_mount *mp = bp->b_mount;
|
||||
|
||||
xfs_alert_tag(mp, XFS_PTAG_VERIFIER_ERROR,
|
||||
"Metadata corruption detected at %pS, %s block 0x%llx",
|
||||
__return_address, bp->b_ops->name, bp->b_bn);
|
||||
|
||||
xfs_alert(mp, "Unmount and run xfs_repair");
|
||||
|
||||
if (xfs_error_level >= XFS_ERRLEVEL_HIGH)
|
||||
xfs_stack_trace();
|
||||
}
|
||||
|
||||
/*
|
||||
* Warnings specifically for verifier errors. Differentiate CRC vs. invalid
|
||||
* values, and omit the stack trace unless the error level is tuned high.
|
||||
@ -350,7 +371,7 @@ xfs_buf_verifier_error(
|
||||
struct xfs_buf *bp,
|
||||
int error,
|
||||
const char *name,
|
||||
void *buf,
|
||||
const void *buf,
|
||||
size_t bufsz,
|
||||
xfs_failaddr_t failaddr)
|
||||
{
|
||||
@ -402,7 +423,7 @@ xfs_inode_verifier_error(
|
||||
struct xfs_inode *ip,
|
||||
int error,
|
||||
const char *name,
|
||||
void *buf,
|
||||
const void *buf,
|
||||
size_t bufsz,
|
||||
xfs_failaddr_t failaddr)
|
||||
{
|
||||
|
@ -12,16 +12,17 @@ extern void xfs_error_report(const char *tag, int level, struct xfs_mount *mp,
|
||||
const char *filename, int linenum,
|
||||
xfs_failaddr_t failaddr);
|
||||
extern void xfs_corruption_error(const char *tag, int level,
|
||||
struct xfs_mount *mp, void *buf, size_t bufsize,
|
||||
struct xfs_mount *mp, const void *buf, size_t bufsize,
|
||||
const char *filename, int linenum,
|
||||
xfs_failaddr_t failaddr);
|
||||
void xfs_buf_corruption_error(struct xfs_buf *bp);
|
||||
extern void xfs_buf_verifier_error(struct xfs_buf *bp, int error,
|
||||
const char *name, void *buf, size_t bufsz,
|
||||
const char *name, const void *buf, size_t bufsz,
|
||||
xfs_failaddr_t failaddr);
|
||||
extern void xfs_verifier_error(struct xfs_buf *bp, int error,
|
||||
xfs_failaddr_t failaddr);
|
||||
extern void xfs_inode_verifier_error(struct xfs_inode *ip, int error,
|
||||
const char *name, void *buf, size_t bufsz,
|
||||
const char *name, const void *buf, size_t bufsz,
|
||||
xfs_failaddr_t failaddr);
|
||||
|
||||
#define XFS_ERROR_REPORT(e, lvl, mp) \
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "xfs_alloc.h"
|
||||
#include "xfs_bmap.h"
|
||||
#include "xfs_trace.h"
|
||||
|
||||
#include "xfs_error.h"
|
||||
|
||||
kmem_zone_t *xfs_efi_zone;
|
||||
kmem_zone_t *xfs_efd_zone;
|
||||
@ -228,6 +228,7 @@ xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
@ -624,7 +625,7 @@ xfs_efi_recover(
|
||||
*/
|
||||
set_bit(XFS_EFI_RECOVERED, &efip->efi_flags);
|
||||
xfs_efi_release(efip);
|
||||
return -EIO;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,6 +146,7 @@ xfs_fsmap_owner_from_rmap(
|
||||
dest->fmr_owner = XFS_FMR_OWN_FREE;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
return 0;
|
||||
|
@ -2149,8 +2149,10 @@ xfs_iunlink_update_bucket(
|
||||
* passed in because either we're adding or removing ourselves from the
|
||||
* head of the list.
|
||||
*/
|
||||
if (old_value == new_agino)
|
||||
if (old_value == new_agino) {
|
||||
xfs_buf_corruption_error(agibp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
agi->agi_unlinked[bucket_index] = cpu_to_be32(new_agino);
|
||||
offset = offsetof(struct xfs_agi, agi_unlinked) +
|
||||
@ -2213,6 +2215,8 @@ xfs_iunlink_update_inode(
|
||||
/* Make sure the old pointer isn't garbage. */
|
||||
old_value = be32_to_cpu(dip->di_next_unlinked);
|
||||
if (!xfs_verify_agino_or_null(mp, agno, old_value)) {
|
||||
xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip,
|
||||
sizeof(*dip), __this_address);
|
||||
error = -EFSCORRUPTED;
|
||||
goto out;
|
||||
}
|
||||
@ -2224,8 +2228,11 @@ xfs_iunlink_update_inode(
|
||||
*/
|
||||
*old_next_agino = old_value;
|
||||
if (old_value == next_agino) {
|
||||
if (next_agino != NULLAGINO)
|
||||
if (next_agino != NULLAGINO) {
|
||||
xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__,
|
||||
dip, sizeof(*dip), __this_address);
|
||||
error = -EFSCORRUPTED;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -2276,8 +2283,10 @@ xfs_iunlink(
|
||||
*/
|
||||
next_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]);
|
||||
if (next_agino == agino ||
|
||||
!xfs_verify_agino_or_null(mp, agno, next_agino))
|
||||
!xfs_verify_agino_or_null(mp, agno, next_agino)) {
|
||||
xfs_buf_corruption_error(agibp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
if (next_agino != NULLAGINO) {
|
||||
struct xfs_perag *pag;
|
||||
@ -3215,6 +3224,7 @@ xfs_rename(
|
||||
struct xfs_trans *tp;
|
||||
struct xfs_inode *wip = NULL; /* whiteout inode */
|
||||
struct xfs_inode *inodes[__XFS_SORT_INODES];
|
||||
int i;
|
||||
int num_inodes = __XFS_SORT_INODES;
|
||||
bool new_parent = (src_dp != target_dp);
|
||||
bool src_is_directory = S_ISDIR(VFS_I(src_ip)->i_mode);
|
||||
@ -3326,6 +3336,30 @@ xfs_rename(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Lock the AGI buffers we need to handle bumping the nlink of the
|
||||
* whiteout inode off the unlinked list and to handle dropping the
|
||||
* nlink of the target inode. Per locking order rules, do this in
|
||||
* increasing AG order and before directory block allocation tries to
|
||||
* grab AGFs because we grab AGIs before AGFs.
|
||||
*
|
||||
* The (vfs) caller must ensure that if src is a directory then
|
||||
* target_ip is either null or an empty directory.
|
||||
*/
|
||||
for (i = 0; i < num_inodes && inodes[i] != NULL; i++) {
|
||||
if (inodes[i] == wip ||
|
||||
(inodes[i] == target_ip &&
|
||||
(VFS_I(target_ip)->i_nlink == 1 || src_is_directory))) {
|
||||
struct xfs_buf *bp;
|
||||
xfs_agnumber_t agno;
|
||||
|
||||
agno = XFS_INO_TO_AGNO(mp, inodes[i]->i_ino);
|
||||
error = xfs_read_agi(mp, tp, agno, &bp);
|
||||
if (error)
|
||||
goto out_trans_cancel;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Directory entry creation below may acquire the AGF. Remove
|
||||
* the whiteout from the unlinked list first to preserve correct
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "xfs_trans_priv.h"
|
||||
#include "xfs_buf_item.h"
|
||||
#include "xfs_log.h"
|
||||
#include "xfs_error.h"
|
||||
|
||||
#include <linux/iversion.h>
|
||||
|
||||
@ -828,8 +829,10 @@ xfs_inode_item_format_convert(
|
||||
{
|
||||
struct xfs_inode_log_format_32 *in_f32 = buf->i_addr;
|
||||
|
||||
if (buf->i_len != sizeof(*in_f32))
|
||||
if (buf->i_len != sizeof(*in_f32)) {
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
in_f->ilf_type = in_f32->ilf_type;
|
||||
in_f->ilf_size = in_f32->ilf_size;
|
||||
|
@ -765,6 +765,11 @@ xfs_iomap_write_unwritten(
|
||||
*/
|
||||
resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1;
|
||||
|
||||
/* Attach dquots so that bmbt splits are accounted correctly. */
|
||||
error = xfs_qm_dqattach(ip);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
do {
|
||||
/*
|
||||
* Set up a transaction to convert the range of extents
|
||||
@ -783,6 +788,11 @@ xfs_iomap_write_unwritten(
|
||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||
xfs_trans_ijoin(tp, ip, 0);
|
||||
|
||||
error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0,
|
||||
XFS_QMOPT_RES_REGBLKS);
|
||||
if (error)
|
||||
goto error_on_bmapi_transaction;
|
||||
|
||||
/*
|
||||
* Modify the unwritten extent state of the buffer.
|
||||
*/
|
||||
@ -1055,6 +1065,13 @@ xfs_file_iomap_begin(
|
||||
trace_xfs_iomap_alloc(ip, offset, length, XFS_DATA_FORK, &imap);
|
||||
|
||||
out_finish:
|
||||
/*
|
||||
* Writes that span EOF might trigger an IO size update on completion,
|
||||
* so consider them to be dirty for the purposes of O_DSYNC even if
|
||||
* there is no other metadata changes pending or have been made here.
|
||||
*/
|
||||
if ((flags & IOMAP_WRITE) && offset + length > i_size_read(inode))
|
||||
iomap->flags |= IOMAP_F_DIRTY;
|
||||
return xfs_bmbt_to_iomap(ip, iomap, &imap, shared);
|
||||
|
||||
out_found:
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "xfs_symlink.h"
|
||||
#include "xfs_dir2.h"
|
||||
#include "xfs_iomap.h"
|
||||
#include "xfs_error.h"
|
||||
|
||||
#include <linux/xattr.h>
|
||||
#include <linux/posix_acl.h>
|
||||
@ -470,17 +471,20 @@ xfs_vn_get_link_inline(
|
||||
struct inode *inode,
|
||||
struct delayed_call *done)
|
||||
{
|
||||
struct xfs_inode *ip = XFS_I(inode);
|
||||
char *link;
|
||||
|
||||
ASSERT(XFS_I(inode)->i_df.if_flags & XFS_IFINLINE);
|
||||
ASSERT(ip->i_df.if_flags & XFS_IFINLINE);
|
||||
|
||||
/*
|
||||
* The VFS crashes on a NULL pointer, so return -EFSCORRUPTED if
|
||||
* if_data is junk.
|
||||
*/
|
||||
link = XFS_I(inode)->i_df.if_u1.if_data;
|
||||
if (!link)
|
||||
link = ip->i_df.if_u1.if_data;
|
||||
if (!link) {
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, ip->i_mount);
|
||||
return ERR_PTR(-EFSCORRUPTED);
|
||||
}
|
||||
return link;
|
||||
}
|
||||
|
||||
|
@ -471,7 +471,7 @@ xlog_find_verify_log_record(
|
||||
xfs_warn(log->l_mp,
|
||||
"Log inconsistent (didn't find previous header)");
|
||||
ASSERT(0);
|
||||
error = -EIO;
|
||||
error = -EFSCORRUPTED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -1347,10 +1347,11 @@ xlog_find_tail(
|
||||
error = xlog_rseek_logrec_hdr(log, *head_blk, *head_blk, 1, buffer,
|
||||
&rhead_blk, &rhead, &wrapped);
|
||||
if (error < 0)
|
||||
return error;
|
||||
goto done;
|
||||
if (!error) {
|
||||
xfs_warn(log->l_mp, "%s: couldn't find sync record", __func__);
|
||||
return -EIO;
|
||||
error = -EFSCORRUPTED;
|
||||
goto done;
|
||||
}
|
||||
*tail_blk = BLOCK_LSN(be64_to_cpu(rhead->h_tail_lsn));
|
||||
|
||||
@ -3166,7 +3167,7 @@ xlog_recover_inode_pass2(
|
||||
default:
|
||||
xfs_warn(log->l_mp, "%s: Invalid flag", __func__);
|
||||
ASSERT(0);
|
||||
error = -EIO;
|
||||
error = -EFSCORRUPTED;
|
||||
goto out_release;
|
||||
}
|
||||
}
|
||||
@ -3247,12 +3248,12 @@ xlog_recover_dquot_pass2(
|
||||
recddq = item->ri_buf[1].i_addr;
|
||||
if (recddq == NULL) {
|
||||
xfs_alert(log->l_mp, "NULL dquot in %s.", __func__);
|
||||
return -EIO;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
if (item->ri_buf[1].i_len < sizeof(xfs_disk_dquot_t)) {
|
||||
xfs_alert(log->l_mp, "dquot too small (%d) in %s.",
|
||||
item->ri_buf[1].i_len, __func__);
|
||||
return -EIO;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3279,7 +3280,7 @@ xlog_recover_dquot_pass2(
|
||||
if (fa) {
|
||||
xfs_alert(mp, "corrupt dquot ID 0x%x in log at %pS",
|
||||
dq_f->qlf_id, fa);
|
||||
return -EIO;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
ASSERT(dq_f->qlf_len == 1);
|
||||
|
||||
@ -3537,6 +3538,7 @@ xfs_cui_copy_format(
|
||||
memcpy(dst_cui_fmt, src_cui_fmt, len);
|
||||
return 0;
|
||||
}
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
@ -3601,8 +3603,10 @@ xlog_recover_cud_pass2(
|
||||
struct xfs_ail *ailp = log->l_ailp;
|
||||
|
||||
cud_formatp = item->ri_buf[0].i_addr;
|
||||
if (item->ri_buf[0].i_len != sizeof(struct xfs_cud_log_format))
|
||||
if (item->ri_buf[0].i_len != sizeof(struct xfs_cud_log_format)) {
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
cui_id = cud_formatp->cud_cui_id;
|
||||
|
||||
/*
|
||||
@ -3654,6 +3658,7 @@ xfs_bui_copy_format(
|
||||
memcpy(dst_bui_fmt, src_bui_fmt, len);
|
||||
return 0;
|
||||
}
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
@ -3677,8 +3682,10 @@ xlog_recover_bui_pass2(
|
||||
|
||||
bui_formatp = item->ri_buf[0].i_addr;
|
||||
|
||||
if (bui_formatp->bui_nextents != XFS_BUI_MAX_FAST_EXTENTS)
|
||||
if (bui_formatp->bui_nextents != XFS_BUI_MAX_FAST_EXTENTS) {
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
buip = xfs_bui_init(mp);
|
||||
error = xfs_bui_copy_format(&item->ri_buf[0], &buip->bui_format);
|
||||
if (error) {
|
||||
@ -3720,8 +3727,10 @@ xlog_recover_bud_pass2(
|
||||
struct xfs_ail *ailp = log->l_ailp;
|
||||
|
||||
bud_formatp = item->ri_buf[0].i_addr;
|
||||
if (item->ri_buf[0].i_len != sizeof(struct xfs_bud_log_format))
|
||||
if (item->ri_buf[0].i_len != sizeof(struct xfs_bud_log_format)) {
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
bui_id = bud_formatp->bud_bui_id;
|
||||
|
||||
/*
|
||||
@ -4018,7 +4027,7 @@ xlog_recover_commit_pass1(
|
||||
xfs_warn(log->l_mp, "%s: invalid item type (%d)",
|
||||
__func__, ITEM_TYPE(item));
|
||||
ASSERT(0);
|
||||
return -EIO;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4066,7 +4075,7 @@ xlog_recover_commit_pass2(
|
||||
xfs_warn(log->l_mp, "%s: invalid item type (%d)",
|
||||
__func__, ITEM_TYPE(item));
|
||||
ASSERT(0);
|
||||
return -EIO;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4187,7 +4196,7 @@ xlog_recover_add_to_cont_trans(
|
||||
ASSERT(len <= sizeof(struct xfs_trans_header));
|
||||
if (len > sizeof(struct xfs_trans_header)) {
|
||||
xfs_warn(log->l_mp, "%s: bad header length", __func__);
|
||||
return -EIO;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
xlog_recover_add_item(&trans->r_itemq);
|
||||
@ -4243,13 +4252,13 @@ xlog_recover_add_to_trans(
|
||||
xfs_warn(log->l_mp, "%s: bad header magic number",
|
||||
__func__);
|
||||
ASSERT(0);
|
||||
return -EIO;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
if (len > sizeof(struct xfs_trans_header)) {
|
||||
xfs_warn(log->l_mp, "%s: bad header length", __func__);
|
||||
ASSERT(0);
|
||||
return -EIO;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4285,7 +4294,7 @@ xlog_recover_add_to_trans(
|
||||
in_f->ilf_size);
|
||||
ASSERT(0);
|
||||
kmem_free(ptr);
|
||||
return -EIO;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
item->ri_total = in_f->ilf_size;
|
||||
@ -4293,7 +4302,16 @@ xlog_recover_add_to_trans(
|
||||
kmem_zalloc(item->ri_total * sizeof(xfs_log_iovec_t),
|
||||
0);
|
||||
}
|
||||
ASSERT(item->ri_total > item->ri_cnt);
|
||||
|
||||
if (item->ri_total <= item->ri_cnt) {
|
||||
xfs_warn(log->l_mp,
|
||||
"log item region count (%d) overflowed size (%d)",
|
||||
item->ri_cnt, item->ri_total);
|
||||
ASSERT(0);
|
||||
kmem_free(ptr);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
/* Description region is ri_buf[0] */
|
||||
item->ri_buf[item->ri_cnt].i_addr = ptr;
|
||||
item->ri_buf[item->ri_cnt].i_len = len;
|
||||
@ -4380,7 +4398,7 @@ xlog_recovery_process_trans(
|
||||
default:
|
||||
xfs_warn(log->l_mp, "%s: bad flag 0x%x", __func__, flags);
|
||||
ASSERT(0);
|
||||
error = -EIO;
|
||||
error = -EFSCORRUPTED;
|
||||
break;
|
||||
}
|
||||
if (error || freeit)
|
||||
@ -4460,7 +4478,7 @@ xlog_recover_process_ophdr(
|
||||
xfs_warn(log->l_mp, "%s: bad clientid 0x%x",
|
||||
__func__, ohead->oh_clientid);
|
||||
ASSERT(0);
|
||||
return -EIO;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4470,7 +4488,7 @@ xlog_recover_process_ophdr(
|
||||
if (dp + len > end) {
|
||||
xfs_warn(log->l_mp, "%s: bad length 0x%x", __func__, len);
|
||||
WARN_ON(1);
|
||||
return -EIO;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
trans = xlog_recover_ophdr_to_trans(rhash, rhead, ohead);
|
||||
@ -5172,8 +5190,10 @@ xlog_recover_process(
|
||||
* If the filesystem is CRC enabled, this mismatch becomes a
|
||||
* fatal log corruption failure.
|
||||
*/
|
||||
if (xfs_sb_version_hascrc(&log->l_mp->m_sb))
|
||||
if (xfs_sb_version_hascrc(&log->l_mp->m_sb)) {
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
}
|
||||
|
||||
xlog_unpack_data(rhead, dp, log);
|
||||
@ -5200,7 +5220,7 @@ xlog_valid_rec_header(
|
||||
(be32_to_cpu(rhead->h_version) & (~XLOG_VERSION_OKBITS))))) {
|
||||
xfs_warn(log->l_mp, "%s: unrecognised log version (%d).",
|
||||
__func__, be32_to_cpu(rhead->h_version));
|
||||
return -EIO;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
/* LR body must have data or it wouldn't have been written */
|
||||
@ -5296,8 +5316,12 @@ xlog_do_recovery_pass(
|
||||
"invalid iclog size (%d bytes), using lsunit (%d bytes)",
|
||||
h_size, log->l_mp->m_logbsize);
|
||||
h_size = log->l_mp->m_logbsize;
|
||||
} else
|
||||
return -EFSCORRUPTED;
|
||||
} else {
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW,
|
||||
log->l_mp);
|
||||
error = -EFSCORRUPTED;
|
||||
goto bread_err1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((be32_to_cpu(rhead->h_version) & XLOG_VERSION_2) &&
|
||||
|
@ -105,7 +105,7 @@ assfail(char *expr, char *file, int line)
|
||||
}
|
||||
|
||||
void
|
||||
xfs_hex_dump(void *p, int length)
|
||||
xfs_hex_dump(const void *p, int length)
|
||||
{
|
||||
print_hex_dump(KERN_ALERT, "", DUMP_PREFIX_OFFSET, 16, 1, p, length, 1);
|
||||
}
|
||||
|
@ -60,6 +60,6 @@ do { \
|
||||
extern void assfail(char *expr, char *f, int l);
|
||||
extern void asswarn(char *expr, char *f, int l);
|
||||
|
||||
extern void xfs_hex_dump(void *p, int length);
|
||||
extern void xfs_hex_dump(const void *p, int length);
|
||||
|
||||
#endif /* __XFS_MESSAGE_H */
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include "xfs_reflink.h"
|
||||
#include "xfs_extent_busy.h"
|
||||
#include "xfs_health.h"
|
||||
|
||||
#include "xfs_trace.h"
|
||||
|
||||
static DEFINE_MUTEX(xfs_uuid_table_mutex);
|
||||
static int xfs_uuid_table_size;
|
||||
@ -365,66 +365,119 @@ xfs_readsb(
|
||||
}
|
||||
|
||||
/*
|
||||
* Update alignment values based on mount options and sb values
|
||||
* If the sunit/swidth change would move the precomputed root inode value, we
|
||||
* must reject the ondisk change because repair will stumble over that.
|
||||
* However, we allow the mount to proceed because we never rejected this
|
||||
* combination before. Returns true to update the sb, false otherwise.
|
||||
*/
|
||||
static inline int
|
||||
xfs_check_new_dalign(
|
||||
struct xfs_mount *mp,
|
||||
int new_dalign,
|
||||
bool *update_sb)
|
||||
{
|
||||
struct xfs_sb *sbp = &mp->m_sb;
|
||||
xfs_ino_t calc_ino;
|
||||
|
||||
calc_ino = xfs_ialloc_calc_rootino(mp, new_dalign);
|
||||
trace_xfs_check_new_dalign(mp, new_dalign, calc_ino);
|
||||
|
||||
if (sbp->sb_rootino == calc_ino) {
|
||||
*update_sb = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
xfs_warn(mp,
|
||||
"Cannot change stripe alignment; would require moving root inode.");
|
||||
|
||||
/*
|
||||
* XXX: Next time we add a new incompat feature, this should start
|
||||
* returning -EINVAL to fail the mount. Until then, spit out a warning
|
||||
* that we're ignoring the administrator's instructions.
|
||||
*/
|
||||
xfs_warn(mp, "Skipping superblock stripe alignment update.");
|
||||
*update_sb = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we were provided with new sunit/swidth values as mount options, make sure
|
||||
* that they pass basic alignment and superblock feature checks, and convert
|
||||
* them into the same units (FSB) that everything else expects. This step
|
||||
* /must/ be done before computing the inode geometry.
|
||||
*/
|
||||
STATIC int
|
||||
xfs_update_alignment(xfs_mount_t *mp)
|
||||
xfs_validate_new_dalign(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
xfs_sb_t *sbp = &(mp->m_sb);
|
||||
if (mp->m_dalign == 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If stripe unit and stripe width are not multiples
|
||||
* of the fs blocksize turn off alignment.
|
||||
*/
|
||||
if ((BBTOB(mp->m_dalign) & mp->m_blockmask) ||
|
||||
(BBTOB(mp->m_swidth) & mp->m_blockmask)) {
|
||||
xfs_warn(mp,
|
||||
"alignment check failed: sunit/swidth vs. blocksize(%d)",
|
||||
mp->m_sb.sb_blocksize);
|
||||
return -EINVAL;
|
||||
} else {
|
||||
/*
|
||||
* Convert the stripe unit and width to FSBs.
|
||||
*/
|
||||
mp->m_dalign = XFS_BB_TO_FSBT(mp, mp->m_dalign);
|
||||
if (mp->m_dalign && (mp->m_sb.sb_agblocks % mp->m_dalign)) {
|
||||
xfs_warn(mp,
|
||||
"alignment check failed: sunit/swidth vs. agsize(%d)",
|
||||
mp->m_sb.sb_agblocks);
|
||||
return -EINVAL;
|
||||
} else if (mp->m_dalign) {
|
||||
mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth);
|
||||
} else {
|
||||
xfs_warn(mp,
|
||||
"alignment check failed: sunit(%d) less than bsize(%d)",
|
||||
mp->m_dalign, mp->m_sb.sb_blocksize);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!xfs_sb_version_hasdalign(&mp->m_sb)) {
|
||||
xfs_warn(mp,
|
||||
"cannot change alignment: superblock does not support data alignment");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Update alignment values based on mount options and sb values. */
|
||||
STATIC int
|
||||
xfs_update_alignment(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
struct xfs_sb *sbp = &mp->m_sb;
|
||||
|
||||
if (mp->m_dalign) {
|
||||
/*
|
||||
* If stripe unit and stripe width are not multiples
|
||||
* of the fs blocksize turn off alignment.
|
||||
*/
|
||||
if ((BBTOB(mp->m_dalign) & mp->m_blockmask) ||
|
||||
(BBTOB(mp->m_swidth) & mp->m_blockmask)) {
|
||||
xfs_warn(mp,
|
||||
"alignment check failed: sunit/swidth vs. blocksize(%d)",
|
||||
sbp->sb_blocksize);
|
||||
return -EINVAL;
|
||||
} else {
|
||||
/*
|
||||
* Convert the stripe unit and width to FSBs.
|
||||
*/
|
||||
mp->m_dalign = XFS_BB_TO_FSBT(mp, mp->m_dalign);
|
||||
if (mp->m_dalign && (sbp->sb_agblocks % mp->m_dalign)) {
|
||||
xfs_warn(mp,
|
||||
"alignment check failed: sunit/swidth vs. agsize(%d)",
|
||||
sbp->sb_agblocks);
|
||||
return -EINVAL;
|
||||
} else if (mp->m_dalign) {
|
||||
mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth);
|
||||
} else {
|
||||
xfs_warn(mp,
|
||||
"alignment check failed: sunit(%d) less than bsize(%d)",
|
||||
mp->m_dalign, sbp->sb_blocksize);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
bool update_sb;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Update superblock with new values
|
||||
* and log changes
|
||||
*/
|
||||
if (xfs_sb_version_hasdalign(sbp)) {
|
||||
if (sbp->sb_unit != mp->m_dalign) {
|
||||
sbp->sb_unit = mp->m_dalign;
|
||||
mp->m_update_sb = true;
|
||||
}
|
||||
if (sbp->sb_width != mp->m_swidth) {
|
||||
sbp->sb_width = mp->m_swidth;
|
||||
mp->m_update_sb = true;
|
||||
}
|
||||
} else {
|
||||
xfs_warn(mp,
|
||||
"cannot change alignment: superblock does not support data alignment");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (sbp->sb_unit == mp->m_dalign &&
|
||||
sbp->sb_width == mp->m_swidth)
|
||||
return 0;
|
||||
|
||||
error = xfs_check_new_dalign(mp, mp->m_dalign, &update_sb);
|
||||
if (error || !update_sb)
|
||||
return error;
|
||||
|
||||
sbp->sb_unit = mp->m_dalign;
|
||||
sbp->sb_width = mp->m_swidth;
|
||||
mp->m_update_sb = true;
|
||||
} else if ((mp->m_flags & XFS_MOUNT_NOALIGN) != XFS_MOUNT_NOALIGN &&
|
||||
xfs_sb_version_hasdalign(&mp->m_sb)) {
|
||||
mp->m_dalign = sbp->sb_unit;
|
||||
mp->m_swidth = sbp->sb_width;
|
||||
mp->m_dalign = sbp->sb_unit;
|
||||
mp->m_swidth = sbp->sb_width;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -692,12 +745,12 @@ xfs_mountfs(
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if sb_agblocks is aligned at stripe boundary
|
||||
* If sb_agblocks is NOT aligned turn off m_dalign since
|
||||
* allocator alignment is within an ag, therefore ag has
|
||||
* to be aligned at stripe boundary.
|
||||
* If we were given new sunit/swidth options, do some basic validation
|
||||
* checks and convert the incore dalign and swidth values to the
|
||||
* same units (FSB) that everything else uses. This /must/ happen
|
||||
* before computing the inode geometry.
|
||||
*/
|
||||
error = xfs_update_alignment(mp);
|
||||
error = xfs_validate_new_dalign(mp);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
@ -708,6 +761,17 @@ xfs_mountfs(
|
||||
xfs_rmapbt_compute_maxlevels(mp);
|
||||
xfs_refcountbt_compute_maxlevels(mp);
|
||||
|
||||
/*
|
||||
* Check if sb_agblocks is aligned at stripe boundary. If sb_agblocks
|
||||
* is NOT aligned turn off m_dalign since allocator alignment is within
|
||||
* an ag, therefore ag has to be aligned at stripe boundary. Note that
|
||||
* we must compute the free space and rmap btree geometry before doing
|
||||
* this.
|
||||
*/
|
||||
error = xfs_update_alignment(mp);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
/* enable fail_at_unmount as default */
|
||||
mp->m_fail_unmount = true;
|
||||
|
||||
|
@ -147,11 +147,11 @@ xfs_fs_map_blocks(
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
|
||||
ASSERT(!nimaps || imap.br_startblock != DELAYSTARTBLOCK);
|
||||
|
||||
if (write) {
|
||||
enum xfs_prealloc_flags flags = 0;
|
||||
|
||||
ASSERT(imap.br_startblock != DELAYSTARTBLOCK);
|
||||
|
||||
if (!nimaps || imap.br_startblock == HOLESTARTBLOCK) {
|
||||
/*
|
||||
* xfs_iomap_write_direct() expects to take ownership of
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "xfs_qm.h"
|
||||
#include "xfs_trace.h"
|
||||
#include "xfs_icache.h"
|
||||
#include "xfs_error.h"
|
||||
|
||||
/*
|
||||
* The global quota manager. There is only one of these for the entire
|
||||
@ -754,11 +755,19 @@ xfs_qm_qino_alloc(
|
||||
if ((flags & XFS_QMOPT_PQUOTA) &&
|
||||
(mp->m_sb.sb_gquotino != NULLFSINO)) {
|
||||
ino = mp->m_sb.sb_gquotino;
|
||||
ASSERT(mp->m_sb.sb_pquotino == NULLFSINO);
|
||||
if (mp->m_sb.sb_pquotino != NULLFSINO) {
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW,
|
||||
mp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
} else if ((flags & XFS_QMOPT_GQUOTA) &&
|
||||
(mp->m_sb.sb_pquotino != NULLFSINO)) {
|
||||
ino = mp->m_sb.sb_pquotino;
|
||||
ASSERT(mp->m_sb.sb_gquotino == NULLFSINO);
|
||||
if (mp->m_sb.sb_gquotino != NULLFSINO) {
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW,
|
||||
mp);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
}
|
||||
if (ino != NULLFSINO) {
|
||||
error = xfs_iget(mp, NULL, ino, 0, 0, ip);
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "xfs_refcount_item.h"
|
||||
#include "xfs_log.h"
|
||||
#include "xfs_refcount.h"
|
||||
|
||||
#include "xfs_error.h"
|
||||
|
||||
kmem_zone_t *xfs_cui_zone;
|
||||
kmem_zone_t *xfs_cud_zone;
|
||||
@ -497,7 +497,7 @@ xfs_cui_recover(
|
||||
*/
|
||||
set_bit(XFS_CUI_RECOVERED, &cuip->cui_flags);
|
||||
xfs_cui_release(cuip);
|
||||
return -EIO;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
}
|
||||
|
||||
@ -536,6 +536,7 @@ xfs_cui_recover(
|
||||
type = refc_type;
|
||||
break;
|
||||
default:
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
|
||||
error = -EFSCORRUPTED;
|
||||
goto abort_error;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "xfs_rmap_item.h"
|
||||
#include "xfs_log.h"
|
||||
#include "xfs_rmap.h"
|
||||
|
||||
#include "xfs_error.h"
|
||||
|
||||
kmem_zone_t *xfs_rui_zone;
|
||||
kmem_zone_t *xfs_rud_zone;
|
||||
@ -171,8 +171,10 @@ xfs_rui_copy_format(
|
||||
src_rui_fmt = buf->i_addr;
|
||||
len = xfs_rui_log_format_sizeof(src_rui_fmt->rui_nextents);
|
||||
|
||||
if (buf->i_len != len)
|
||||
if (buf->i_len != len) {
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
memcpy(dst_rui_fmt, src_rui_fmt, len);
|
||||
return 0;
|
||||
@ -539,7 +541,7 @@ xfs_rui_recover(
|
||||
*/
|
||||
set_bit(XFS_RUI_RECOVERED, &ruip->rui_flags);
|
||||
xfs_rui_release(ruip);
|
||||
return -EIO;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
}
|
||||
|
||||
@ -581,6 +583,7 @@ xfs_rui_recover(
|
||||
type = XFS_RMAP_FREE;
|
||||
break;
|
||||
default:
|
||||
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
|
||||
error = -EFSCORRUPTED;
|
||||
goto abort_error;
|
||||
}
|
||||
|
@ -3609,6 +3609,27 @@ DEFINE_KMEM_EVENT(kmem_alloc_large);
|
||||
DEFINE_KMEM_EVENT(kmem_realloc);
|
||||
DEFINE_KMEM_EVENT(kmem_zone_alloc);
|
||||
|
||||
TRACE_EVENT(xfs_check_new_dalign,
|
||||
TP_PROTO(struct xfs_mount *mp, int new_dalign, xfs_ino_t calc_rootino),
|
||||
TP_ARGS(mp, new_dalign, calc_rootino),
|
||||
TP_STRUCT__entry(
|
||||
__field(dev_t, dev)
|
||||
__field(int, new_dalign)
|
||||
__field(xfs_ino_t, sb_rootino)
|
||||
__field(xfs_ino_t, calc_rootino)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->dev = mp->m_super->s_dev;
|
||||
__entry->new_dalign = new_dalign;
|
||||
__entry->sb_rootino = mp->m_sb.sb_rootino;
|
||||
__entry->calc_rootino = calc_rootino;
|
||||
),
|
||||
TP_printk("dev %d:%d new_dalign %d sb_rootino %llu calc_rootino %llu",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->new_dalign, __entry->sb_rootino,
|
||||
__entry->calc_rootino)
|
||||
)
|
||||
|
||||
#endif /* _TRACE_XFS_H */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
|
@ -33,6 +33,8 @@ struct vm_fault;
|
||||
*
|
||||
* IOMAP_F_DIRTY indicates the inode has uncommitted metadata needed to access
|
||||
* written data and requires fdatasync to commit them to persistent storage.
|
||||
* This needs to take into account metadata changes that *may* be made at IO
|
||||
* completion, such as file size updates from direct IO.
|
||||
*/
|
||||
#define IOMAP_F_NEW 0x01 /* blocks have been newly allocated */
|
||||
#define IOMAP_F_DIRTY 0x02 /* uncommitted metadata */
|
||||
|
@ -16,7 +16,7 @@
|
||||
* try_get_task_stack() instead. task_stack_page will return a pointer
|
||||
* that could get freed out from under you.
|
||||
*/
|
||||
static inline void *task_stack_page(const struct task_struct *task)
|
||||
static __always_inline void *task_stack_page(const struct task_struct *task)
|
||||
{
|
||||
return task->stack;
|
||||
}
|
||||
|
@ -297,6 +297,23 @@ struct uart_state {
|
||||
/* number of characters left in xmit buffer before we ask for more */
|
||||
#define WAKEUP_CHARS 256
|
||||
|
||||
/**
|
||||
* uart_xmit_advance - Advance xmit buffer and account Tx'ed chars
|
||||
* @up: uart_port structure describing the port
|
||||
* @chars: number of characters sent
|
||||
*
|
||||
* This function advances the tail of circular xmit buffer by the number of
|
||||
* @chars transmitted and handles accounting of transmitted bytes (into
|
||||
* @up's icount.tx).
|
||||
*/
|
||||
static inline void uart_xmit_advance(struct uart_port *up, unsigned int chars)
|
||||
{
|
||||
struct circ_buf *xmit = &up->state->xmit;
|
||||
|
||||
xmit->tail = (xmit->tail + chars) & (UART_XMIT_SIZE - 1);
|
||||
up->icount.tx += chars;
|
||||
}
|
||||
|
||||
struct module;
|
||||
struct tty_driver;
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/pid_namespace.h>
|
||||
#include <linux/cgroupstats.h>
|
||||
#include <linux/fs_parser.h>
|
||||
#include <linux/cpu.h>
|
||||
|
||||
#include <trace/events/cgroup.h>
|
||||
#include <trace/hooks/cgroup.h>
|
||||
@ -63,6 +64,7 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk)
|
||||
int retval = 0;
|
||||
|
||||
mutex_lock(&cgroup_mutex);
|
||||
cpus_read_lock();
|
||||
percpu_down_write(&cgroup_threadgroup_rwsem);
|
||||
for_each_root(root) {
|
||||
struct cgroup *from_cgrp;
|
||||
@ -79,6 +81,7 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk)
|
||||
break;
|
||||
}
|
||||
percpu_up_write(&cgroup_threadgroup_rwsem);
|
||||
cpus_read_unlock();
|
||||
mutex_unlock(&cgroup_mutex);
|
||||
|
||||
return retval;
|
||||
|
@ -56,14 +56,14 @@ __visible void trace_hardirqs_on_caller(unsigned long caller_addr)
|
||||
this_cpu_write(tracing_irq_cpu, 0);
|
||||
}
|
||||
|
||||
lockdep_hardirqs_on(CALLER_ADDR0);
|
||||
lockdep_hardirqs_on(caller_addr);
|
||||
}
|
||||
EXPORT_SYMBOL(trace_hardirqs_on_caller);
|
||||
NOKPROBE_SYMBOL(trace_hardirqs_on_caller);
|
||||
|
||||
__visible void trace_hardirqs_off_caller(unsigned long caller_addr)
|
||||
{
|
||||
lockdep_hardirqs_off(CALLER_ADDR0);
|
||||
lockdep_hardirqs_off(caller_addr);
|
||||
|
||||
if (!this_cpu_read(tracing_irq_cpu)) {
|
||||
this_cpu_write(tracing_irq_cpu, 1);
|
||||
|
@ -3055,10 +3055,8 @@ static bool __flush_work(struct work_struct *work, bool from_cancel)
|
||||
if (WARN_ON(!work->func))
|
||||
return false;
|
||||
|
||||
if (!from_cancel) {
|
||||
lock_map_acquire(&work->lockdep_map);
|
||||
lock_map_release(&work->lockdep_map);
|
||||
}
|
||||
lock_map_acquire(&work->lockdep_map);
|
||||
lock_map_release(&work->lockdep_map);
|
||||
|
||||
if (start_flush_work(work, &barr, from_cancel)) {
|
||||
wait_for_completion(&barr.done);
|
||||
|
@ -5745,7 +5745,8 @@ static char *create_unique_id(struct kmem_cache *s)
|
||||
char *name = kmalloc(ID_STR_LENGTH, GFP_KERNEL);
|
||||
char *p = name;
|
||||
|
||||
BUG_ON(!name);
|
||||
if (!name)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
*p++ = ':';
|
||||
/*
|
||||
@ -5827,6 +5828,8 @@ static int sysfs_slab_add(struct kmem_cache *s)
|
||||
* for the symlinks.
|
||||
*/
|
||||
name = create_unique_id(s);
|
||||
if (IS_ERR(name))
|
||||
return PTR_ERR(name);
|
||||
}
|
||||
|
||||
s->kobj.kset = kset;
|
||||
|
@ -999,8 +999,10 @@ static int do_replace_finish(struct net *net, struct ebt_replace *repl,
|
||||
goto free_iterate;
|
||||
}
|
||||
|
||||
if (repl->valid_hooks != t->valid_hooks)
|
||||
if (repl->valid_hooks != t->valid_hooks) {
|
||||
ret = -EINVAL;
|
||||
goto free_unlock;
|
||||
}
|
||||
|
||||
if (repl->num_counters && repl->num_counters != t->private->nentries) {
|
||||
ret = -EINVAL;
|
||||
|
@ -435,16 +435,19 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
|
||||
scan_req = rcu_dereference_protected(local->scan_req,
|
||||
lockdep_is_held(&local->mtx));
|
||||
|
||||
if (scan_req != local->int_scan_req) {
|
||||
local->scan_info.aborted = aborted;
|
||||
cfg80211_scan_done(scan_req, &local->scan_info);
|
||||
}
|
||||
RCU_INIT_POINTER(local->scan_req, NULL);
|
||||
RCU_INIT_POINTER(local->scan_sdata, NULL);
|
||||
|
||||
local->scanning = 0;
|
||||
local->scan_chandef.chan = NULL;
|
||||
|
||||
synchronize_rcu();
|
||||
|
||||
if (scan_req != local->int_scan_req) {
|
||||
local->scan_info.aborted = aborted;
|
||||
cfg80211_scan_done(scan_req, &local->scan_info);
|
||||
}
|
||||
|
||||
/* Set power back to normal operating levels. */
|
||||
ieee80211_hw_config(local, 0);
|
||||
|
||||
|
@ -148,15 +148,37 @@ static int help(struct sk_buff *skb, unsigned int protoff,
|
||||
data = ib_ptr;
|
||||
data_limit = ib_ptr + skb->len - dataoff;
|
||||
|
||||
/* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24
|
||||
* 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */
|
||||
while (data < data_limit - (19 + MINMATCHLEN)) {
|
||||
if (memcmp(data, "\1DCC ", 5)) {
|
||||
/* Skip any whitespace */
|
||||
while (data < data_limit - 10) {
|
||||
if (*data == ' ' || *data == '\r' || *data == '\n')
|
||||
data++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* strlen("PRIVMSG x ")=10 */
|
||||
if (data < data_limit - 10) {
|
||||
if (strncasecmp("PRIVMSG ", data, 8))
|
||||
goto out;
|
||||
data += 8;
|
||||
}
|
||||
|
||||
/* strlen(" :\1DCC SENT t AAAAAAAA P\1\n")=26
|
||||
* 7+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=26
|
||||
*/
|
||||
while (data < data_limit - (21 + MINMATCHLEN)) {
|
||||
/* Find first " :", the start of message */
|
||||
if (memcmp(data, " :", 2)) {
|
||||
data++;
|
||||
continue;
|
||||
}
|
||||
data += 2;
|
||||
|
||||
/* then check that place only for the DCC command */
|
||||
if (memcmp(data, "\1DCC ", 5))
|
||||
goto out;
|
||||
data += 5;
|
||||
/* we have at least (19+MINMATCHLEN)-5 bytes valid data left */
|
||||
/* we have at least (21+MINMATCHLEN)-(2+5) bytes valid data left */
|
||||
|
||||
iph = ip_hdr(skb);
|
||||
pr_debug("DCC found in master %pI4:%u %pI4:%u\n",
|
||||
@ -172,7 +194,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
|
||||
pr_debug("DCC %s detected\n", dccprotos[i]);
|
||||
|
||||
/* we have at least
|
||||
* (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid
|
||||
* (21+MINMATCHLEN)-7-dccprotos[i].matchlen bytes valid
|
||||
* data left (== 14/13 bytes) */
|
||||
if (parse_dcc(data, data_limit, &dcc_ip,
|
||||
&dcc_port, &addr_beg_p, &addr_end_p)) {
|
||||
|
@ -477,7 +477,7 @@ static int ct_sip_walk_headers(const struct nf_conn *ct, const char *dptr,
|
||||
return ret;
|
||||
if (ret == 0)
|
||||
break;
|
||||
dataoff += *matchoff;
|
||||
dataoff = *matchoff;
|
||||
}
|
||||
*in_header = 0;
|
||||
}
|
||||
@ -489,7 +489,7 @@ static int ct_sip_walk_headers(const struct nf_conn *ct, const char *dptr,
|
||||
break;
|
||||
if (ret == 0)
|
||||
return ret;
|
||||
dataoff += *matchoff;
|
||||
dataoff = *matchoff;
|
||||
}
|
||||
|
||||
if (in_header)
|
||||
|
@ -269,6 +269,7 @@ bool nf_osf_find(const struct sk_buff *skb,
|
||||
struct nf_osf_hdr_ctx ctx;
|
||||
const struct tcphdr *tcp;
|
||||
struct tcphdr _tcph;
|
||||
bool found = false;
|
||||
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
|
||||
@ -283,10 +284,11 @@ bool nf_osf_find(const struct sk_buff *skb,
|
||||
|
||||
data->genre = f->genre;
|
||||
data->version = f->version;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
return found;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_osf_find);
|
||||
|
||||
|
@ -166,7 +166,7 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j)
|
||||
_enter("{%d,%d}", call->tx_hard_ack, call->tx_top);
|
||||
|
||||
now = ktime_get_real();
|
||||
max_age = ktime_sub(now, jiffies_to_usecs(call->peer->rto_j));
|
||||
max_age = ktime_sub_us(now, jiffies_to_usecs(call->peer->rto_j));
|
||||
|
||||
spin_lock_bh(&call->lock);
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user