5.9.4-rc1 review
Subsystems (6)
Greg Kroah-Hartman
maintainerPATCH 125/391 xfs: avoid LR buffer overrun due to crafted h_len
In reply to Greg Kroah-HartmanFrom: Gao Xiang <[email protected]>
[ Upstream commit f692d09e9c8fd0f5557c2e87f796a16dd95222b8 ]
Currently, crafted h_len has been blocked for the log header of the tail block in commit a70f9fe52daa ("xfs:
detect and handle invalid iclog size set by mkfs").
However, each log record could still have crafted h_len and cause log record buffer overrun. So let's check h_len vs buffer size for each log record as well.
--- fs/xfs/xfs_log_recover.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-)
fs/xfs/xfs_log_recover.c +19 -20
@@ -2904,7 +2904,8 @@ STATIC intxlog_valid_rec_header ( struct xlog *log, struct xlog_rec_header *rhead, - xfs_daddr_t blkno) + xfs_daddr_t blkno, + int bufsize) { int hlen;
@@ -2920,10 +2921,14 @@ xlog_valid_rec_header(return -EFSCORRUPTED ; } -/* LR body must have data or it wouldn't have been written */ +/* +* LR body must have data (or it wouldn't have been written) +* and h_len must not be greater than LR buffer size. +*/ hlen =be32_to_cpu (rhead->h_len); -if (XFS_IS_CORRUPT (log->l_mp, hlen <=0 || hlen >INT_MAX )) +if (XFS_IS_CORRUPT (log->l_mp, hlen <=0 || hlen > bufsize))return -EFSCORRUPTED ; +if (XFS_IS_CORRUPT (log->l_mp, blkno > log->l_logBBsize || blkno >INT_MAX ))return -EFSCORRUPTED ;
@@ -2984,9 +2989,6 @@ xlog_do_recovery_pass( goto bread_err1; rhead = (xlog_rec_header_t *)offset; - error =xlog_valid_rec_header (log, rhead, tail_blk); -if (error) - goto bread_err1;/* * xfsprogs has a bug where record length is based on lsunit but
@@ -3001,21 +3003,18 @@ xlog_do_recovery_pass(*/ h_size =be32_to_cpu (rhead->h_size); h_len =be32_to_cpu (rhead->h_len); -if (h_len > h_size) { -if (h_len <= log->l_mp->m_logbsize && -be32_to_cpu (rhead->h_num_logops) ==1 ) { -xfs_warn (log->l_mp, +if (h_len > h_size && h_len <= log->l_mp->m_logbsize && + rhead->h_num_logops ==cpu_to_be32 (1 )) { +xfs_warn (log->l_mp,"invalid iclog size (%d bytes), using lsunit (%d bytes)" , - h_size, log->l_mp->m_logbsize); - h_size = log->l_mp->m_logbsize; - }else { -XFS_ERROR_REPORT (__func__,XFS_ERRLEVEL_LOW , - log->l_mp); - error = -EFSCORRUPTED ; - goto bread_err1; - } + h_size, log->l_mp->m_logbsize); + h_size = log->l_mp->m_logbsize; } + error =xlog_valid_rec_header (log, rhead, tail_blk, h_size); +if (error) + goto bread_err1; +if ((be32_to_cpu (rhead->h_version) &XLOG_VERSION_2 ) && (h_size >XLOG_HEADER_CYCLE_SIZE )) { hblks = h_size /XLOG_HEADER_CYCLE_SIZE ;
@@ -3096,7 +3095,7 @@ xlog_do_recovery_pass( } rhead = (xlog_rec_header_t *)offset; error =xlog_valid_rec_header (log, rhead, - split_hblks ? blk_no :0 ); + split_hblks ? blk_no :0 , h_size);if (error) goto bread_err2;
@@ -3177,7 +3176,7 @@ xlog_do_recovery_pass( goto bread_err2; rhead = (xlog_rec_header_t *)offset; - error =xlog_valid_rec_header (log, rhead, blk_no); + error =xlog_valid_rec_header (log, rhead, blk_no, h_size);if (error) goto bread_err2;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 126/391 ACPI: Add out of bounds and numa_off protections to pxm_to_node()
In reply to Greg Kroah-HartmanFrom: Jonathan Cameron <[email protected]>
[ Upstream commit 8a3decac087aa897df5af04358c2089e52e70ac4 ]
The function should check the validity of the pxm value before using it to index the pxm_to_node_map[] array.
Whilst hardening this code may be good in general, the main intent here is to enable following patches that use this function to replace acpi_map_pxm_to_node() for non SRAT usecases which should return NO_NUMA_NODE for PXM entries not matching with those in SRAT.
--- drivers/acpi/numa/srat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/numa/srat.c +1 -1
@@ -31,7 +31,7 @@ int acpi_numa __initdata;int pxm_to_node (int pxm) { -if (pxm <0 ) +if (pxm <0 || pxm >=MAX_PXM_DOMAINS || numa_off)return NUMA_NO_NODE ;return pxm_to_node_map[pxm]; }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 127/391 octeontx2-af: fix LD CUSTOM LTYPE aliasing
In reply to Greg Kroah-HartmanFrom: Stanislaw Kardach <[email protected]>
[ Upstream commit 450f0b978870c384dd81d1176088536555f3170e ]
Since LD contains LTYPE definitions tweaked toward efficient NIX_AF_RX_FLOW_KEY_ALG(0..31)_FIELD(0..4) usage, the original location of NPC_LT_LD_CUSTOM0/1 was aliased with MPLS_IN_* definitions. Moving custom frame to value 6 and 7 removes the aliasing at the cost of custom frames being also considered when TCP/UDP RSS algo is configured.
However since the goal of CUSTOM frames is to classify them to a separate set of RQs, this cost is acceptable.
--- drivers/net/ethernet/marvell/octeontx2/af/npc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/marvell/octeontx2/af/npc.h +2 -2
@@ -77,6 +77,8 @@ enum npc_kpu_ld_ltype {NPC_LT_LD_ICMP ,NPC_LT_LD_SCTP ,NPC_LT_LD_ICMP6 , +NPC_LT_LD_CUSTOM0 , +NPC_LT_LD_CUSTOM1 ,NPC_LT_LD_IGMP =8 ,NPC_LT_LD_ESP , NPC_LT_LD_AH,
@@ -85,8 +87,6 @@ enum npc_kpu_ld_ltype {NPC_LT_LD_NSH ,NPC_LT_LD_TU_MPLS_IN_NSH , NPC_LT_LD_TU_MPLS_IN_IP, -NPC_LT_LD_CUSTOM0 =0xE , - NPC_LT_LD_CUSTOM1 = 0xF, }; enum npc_kpu_le_ltype {
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 128/391 brcmfmac: Fix warning message after dongle setup failed
In reply to Greg Kroah-HartmanFrom: Wright Feng <[email protected]>
[ Upstream commit 6aa5a83a7ed8036c1388a811eb8bdfa77b21f19c ]
Brcmfmac showed warning message in fweh.c when checking the size of event queue which is not initialized. Therefore, we only cancel the worker and reset event handler only when it is initialized.
[ 145.505899] brcmfmac 0000:02:00.0: brcmf_pcie_setup: Dongle setup [ 145.929970] ------------[ cut here ]------------ [ 145.929994] WARNING: CPU: 0 PID: 288 at drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c:312 brcmf_fweh_detach+0xbc/0xd0 [brcmfmac] ... [ 145.930029] Call Trace: [ 145.930036] brcmf_detach+0x77/0x100 [brcmfmac] [ 145.930043] brcmf_pcie_remove+0x79/0x130 [brcmfmac] [ 145.930046] pci_device_remove+0x39/0xc0 [ 145.930048] device_release_driver_internal+0x141/0x200 [ 145.930049] device_release_driver+0x12/0x20 [ 145.930054] brcmf_pcie_setup+0x101/0x3c0 [brcmfmac] [ 145.930060] brcmf_fw_request_done+0x11d/0x1f0 [brcmfmac] [ 145.930062] ? lock_timer_base+0x7d/0xa0 [ 145.930063] ? internal_add_timer+0x1f/0xa0 [ 145.930064] ? add_timer+0x11a/0x1d0 [ 145.930066] ? __kmalloc_track_caller+0x18c/0x230 [ 145.930068] ? kstrdup_const+0x23/0x30 [ 145.930069] ? add_dr+0x46/0x80 [ 145.930070] ? devres_add+0x3f/0x50 [ 145.930072] ? usermodehelper_read_unlock+0x15/0x20 [ 145.930073] ? _request_firmware+0x288/0xa20 [ 145.930075] request_firmware_work_func+0x36/0x60 [ 145.930077] process_one_work+0x144/0x360 [ 145.930078] worker_thread+0x4d/0x3c0 [ 145.930079] kthread+0x112/0x150 [ 145.930080] ? rescuer_thread+0x340/0x340 [ 145.930081] ? kthread_park+0x60/0x60 [ 145.930083] ret_from_fork+0x25/0x30
--- .../net/wireless/broadcom/brcm80211/brcmfmac/fweh.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c +6 -4
@@ -304,10 +304,12 @@ void brcmf_fweh_detach(struct brcmf_pub *drvr) {struct brcmf_fweh_info *fweh = &drvr->fweh; -/* cancel the worker */ -cancel_work_sync (&fweh->event_work); -WARN_ON (!list_empty (&fweh->event_q)); -memset (fweh->evt_handler,0 ,sizeof (fweh->evt_handler)); +/* cancel the worker if initialized */ +if (fweh->event_work.func) { +cancel_work_sync (&fweh->event_work); +WARN_ON (!list_empty (&fweh->event_q)); +memset (fweh->evt_handler,0 ,sizeof (fweh->evt_handler)); + } }/**
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 129/391 ath11k: Use GFP_ATOMIC instead of GFP_KERNEL in ath11k_dp_htt_get_ppdu_desc
In reply to Greg Kroah-HartmanFrom: Wen Gong <[email protected]>
[ Upstream commit 6a8be1baa9116a038cb4f6158cc10134387ca0d0 ]
With SLUB DEBUG CONFIG below crash is seen as kmem_cache_alloc is being called in non-atomic context.
To fix this issue, use GFP_ATOMIC instead of GFP_KERNEL kzalloc.
[ 357.217088] BUG: sleeping function called from invalid context at mm/slab.h:498 [ 357.217091] in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 0, name: swapper/0 [ 357.217092] INFO: lockdep is turned off. [ 357.217095] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W 5.9.0-rc5-wt-ath+ #196 [ 357.217096] Hardware name: Intel(R) Client Systems NUC8i7HVK/NUC8i7HVB, BIOS HNKBLi70.86A.0049.2018.0801.1601 08/01/2018 [ 357.217097] Call Trace: [ 357.217098] <IRQ> [ 357.217107] ? ath11k_dp_htt_get_ppdu_desc+0xa9/0x170 [ath11k] [ 357.217110] dump_stack+0x77/0xa0 [ 357.217113] ___might_sleep.cold+0xa6/0xb6 [ 357.217116] kmem_cache_alloc_trace+0x1f2/0x270 [ 357.217122] ath11k_dp_htt_get_ppdu_desc+0xa9/0x170 [ath11k] [ 357.217129] ath11k_htt_pull_ppdu_stats.isra.0+0x96/0x270 [ath11k] [ 357.217135] ath11k_dp_htt_htc_t2h_msg_handler+0xe7/0x1d0 [ath11k] [ 357.217137] ? trace_hardirqs_on+0x1c/0x100 [ 357.217143] ath11k_htc_rx_completion_handler+0x207/0x370 [ath11k] [ 357.217149] ath11k_ce_recv_process_cb+0x15e/0x1e0 [ath11k] [ 357.217151] ? handle_irq_event+0x70/0xa8 [ 357.217154] ath11k_pci_ce_tasklet+0x10/0x30 [ath11k_pci] [ 357.217157] tasklet_action_common.constprop.0+0xd4/0xf0 [ 357.217160] __do_softirq+0xc9/0x482 [ 357.217162] asm_call_on_stack+0x12/0x20 [ 357.217163] </IRQ> [ 357.217166] do_softirq_own_stack+0x49/0x60 [ 357.217167] irq_exit_rcu+0x9a/0xd0 [ 357.217169] common_interrupt+0xa1/0x190 [ 357.217171] asm_common_interrupt+0x1e/0x40 [ 357.217173] RIP: 0010:cpu_idle_poll.isra.0+0x2e/0x60 [ 357.217175] Code: 8b 35 26 27 74 69 e8 11 c8 3d ff e8 bc fa 42 ff e8 e7 9f 4a ff fb 65 48 8b 1c 25 80 90 01 00 48 8b 03 a8 08 74 0b eb 1c f3 90 <48> 8b 03 a8 08 75 13 8b 0 [ 357.217177] RSP: 0018:ffffffff97403ee0 EFLAGS: 00000202 [ 357.217178] RAX: 0000000000000001 RBX: ffffffff9742b8c0 RCX: 0000000000b890ca [ 357.217180] RDX: 0000000000b890ca RSI: 0000000000000001 RDI: ffffffff968d0c49 [ 357.217181] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000001 [ 357.217182] R10: ffffffff9742b8c0 R11: 0000000000000046 R12: 0000000000000000 [ 357.217183] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000066fdf520 [ 357.217186] ? cpu_idle_poll.isra.0+0x19/0x60 [ 357.217189] do_idle+0x5f/0xe0 [ 357.217191] cpu_startup_entry+0x14/0x20 [ 357.217193] start_kernel+0x443/0x464 [ 357.217196] secondary_startup_64+0xa4/0xb0
Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
--- drivers/net/wireless/ath/ath11k/dp_rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/ath/ath11k/dp_rx.c +1 -1
@@ -1421,7 +1421,7 @@ struct htt_ppdu_stats_info *ath11k_dp_htt_get_ppdu_desc(struct ath11k *ar, }spin_unlock_bh (&ar->data_lock); - ppdu_info =kzalloc (sizeof (*ppdu_info),GFP_KERNEL ); + ppdu_info =kzalloc (sizeof (*ppdu_info),GFP_ATOMIC );if (!ppdu_info)return NULL ;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 130/391 ath11k: fix warning caused by lockdep_assert_held
In reply to Greg Kroah-HartmanFrom: Carl Huang <[email protected]>
[ Upstream commit 2f588660e34a982377109872757f1b99d7748d21 ]
Fix warning caused by lockdep_assert_held when CONFIG_LOCKDEP is enabled.
[ 271.940647] WARNING: CPU: 6 PID: 0 at drivers/net/wireless/ath/ath11k/hal.c:818 ath11k_hal_srng_access_begin+0x31/0x40 [ath11k] [ 271.940655] Modules linked in: qrtr_mhi qrtr ns ath11k_pci mhi ath11k qmi_helpers nvme nvme_core [ 271.940675] CPU: 6 PID: 0 Comm: swapper/6 Kdump: loaded Tainted: G W 5.9.0-rc5-kalle-bringup-wt-ath+ #4 [ 271.940682] Hardware name: Dell Inc. Inspiron 7590/08717F, BIOS 1.3.0 07/22/2019 [ 271.940698] RIP: 0010:ath11k_hal_srng_access_begin+0x31/0x40 [ath11k] [ 271.940708] Code: 48 89 f3 85 c0 75 11 48 8b 83 a8 00 00 00 8b 00 89 83 b0 00 00 00 5b c3 48 8d 7e 58 be ff ff ff ff e8 53 24 ec fa 85 c0 75 dd <0f> 0b eb d9 90 66 2e 0f 1f 84 00 00 00 00 00 55 53 48 89 f3 8b 35 [ 271.940718] RSP: 0018:ffffbdf0c0230df8 EFLAGS: 00010246 [ 271.940727] RAX: 0000000000000000 RBX: ffffa12b34e67680 RCX: ffffa12b57a0d800 [ 271.940735] RDX: 0000000000000000 RSI: 00000000ffffffff RDI: ffffa12b34e676d8 [ 271.940742] RBP: ffffa12b34e60000 R08: 0000000000000001 R09: 0000000000000001 [ 271.940753] R10: 0000000000000001 R11: 0000000000000046 R12: 0000000000000000 [ 271.940763] R13: ffffa12b34e60000 R14: ffffa12b34e60000 R15: 0000000000000000 [ 271.940774] FS: 0000000000000000(0000) GS:ffffa12b5a400000(0000) knlGS:0000000000000000 [ 271.940788] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 271.940798] CR2: 00007f8bef282008 CR3: 00000001f4224004 CR4: 00000000003706e0 [ 271.940805] Call Trace: [ 271.940813] <IRQ> [ 271.940835] ath11k_dp_tx_completion_handler+0x9e/0x950 [ath11k] [ 271.940847] ? lock_acquire+0xba/0x3b0 [ 271.940876] ath11k_dp_service_srng+0x5a/0x2e0 [ath11k] [ 271.940893] ath11k_pci_ext_grp_napi_poll+0x1e/0x80 [ath11k_pci] [ 271.940908] net_rx_action+0x283/0x4f0 [ 271.940931] __do_softirq+0xcb/0x499 [ 271.940950] asm_call_on_stack+0x12/0x20 [ 271.940963] </IRQ> [ 271.940979] do_softirq_own_stack+0x4d/0x60 [ 271.940991] irq_exit_rcu+0xb0/0xc0 [ 271.941001] common_interrupt+0xce/0x190 [ 271.941014] asm_common_interrupt+0x1e/0x40 [ 271.941026] RIP: 0010:cpuidle_enter_state+0x115/0x500
Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
--- drivers/net/wireless/ath/ath11k/dp_tx.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/wireless/ath/ath11k/dp_tx.c +4 -0
@@ -514,6 +514,8 @@ void ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id)u32 msdu_id;u8 mac_id; +spin_lock_bh (&status_ring->lock); +ath11k_hal_srng_access_begin (ab, status_ring); while ((ATH11K_TX_COMPL_NEXT(tx_ring->tx_status_head) !=
@@ -533,6 +535,8 @@ void ath11k_dp_tx_completion_handler(struct ath11k_base *ab, int ring_id)ath11k_hal_srng_access_end (ab, status_ring); +spin_unlock_bh (&status_ring->lock); +while (ATH11K_TX_COMPL_NEXT (tx_ring->tx_status_tail) != tx_ring->tx_status_head) {struct hal_wbm_release_ring *tx_status;u32 desc_id;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 131/391 ath11k: change to disable softirqs for ath11k_regd_update to solve deadlock
In reply to Greg Kroah-HartmanFrom: Wen Gong <[email protected]>
[ Upstream commit df648808c6b9989555e247530d8ca0ad0094b361 ]
After base_lock which occupy by ath11k_regd_update, the softirq run for WMI_REG_CHAN_LIST_CC_EVENTID maybe arrived and it also need to accuire the spin lock, then deadlock happend, change to disable softirqis to solve it.
[ 235.576990] ================================
[ 235.576991] WARNING: inconsistent lock state
[ 235.576993] 5.9.0-rc5-wt-ath+ #196 Not tainted
[ 235.576994] --------------------------------
[ 235.576995] inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage.
[ 235.576997] kworker/u16:1/98 [HC0[0]:SC0[0]:HE1:SE1] takes:
[ 235.576998] ffff9655f75cad98 (&ab->base_lock){+.?.}-{2:2}, at: ath11k_regd_update+0x28/0x1d0 [ath11k]
[ 235.577009] {IN-SOFTIRQ-W} state was registered at:
[ 235.577013] __lock_acquire+0x219/0x6e0
[ 235.577015] lock_acquire+0xb6/0x270
[ 235.577018] _raw_spin_lock+0x2c/0x70
[ 235.577023] ath11k_reg_chan_list_event.isra.0+0x10d/0x1e0 [ath11k]
[ 235.577028] ath11k_wmi_tlv_op_rx+0x3c3/0x560 [ath11k]
[ 235.577033] ath11k_htc_rx_completion_handler+0x207/0x370 [ath11k]
[ 235.577039] ath11k_ce_recv_process_cb+0x15e/0x1e0 [ath11k]
[ 235.577041] ath11k_pci_ce_tasklet+0x10/0x30 [ath11k_pci]
[ 235.577043] tasklet_action_common.constprop.0+0xd4/0xf0
[ 235.577045] __do_softirq+0xc9/0x482
[ 235.577046] asm_call_on_stack+0x12/0x20
[ 235.577048] do_softirq_own_stack+0x49/0x60
[ 235.577049] irq_exit_rcu+0x9a/0xd0
[ 235.577050] common_interrupt+0xa1/0x190
[ 235.577052] asm_common_interrupt+0x1e/0x40
[ 235.577053] cpu_idle_poll.isra.0+0x2e/0x60
[ 235.577055] do_idle+0x5f/0xe0
[ 235.577056] cpu_startup_entry+0x14/0x20
[ 235.577058] start_kernel+0x443/0x464
[ 235.577060] secondary_startup_64+0xa4/0xb0
[ 235.577061] irq event stamp: 432035
[ 235.577063] hardirqs last enabled at (432035): [<ffffffff968d12b4>] _raw_spin_unlock_irqrestore+0x34/0x40
[ 235.577064] hardirqs last disabled at (432034): [<ffffffff968d10d3>] _raw_spin_lock_irqsave+0x63/0x80
[ 235.577066] softirqs last enabled at (431998): [<ffffffff967115c1>] inet6_fill_ifla6_attrs+0x3f1/0x430
[ 235.577067] softirqs last disabled at (431996): [<ffffffff9671159f>] inet6_fill_ifla6_attrs+0x3cf/0x430
[ 235.577068]
[ 235.577068] other info that might help us debug this:
[ 235.577069] Possible unsafe locking scenario:
[ 235.577069]
[ 235.577070] CPU0
[ 235.577070] ----
[ 235.577071] lock(&ab->base_lock);
[ 235.577072] <Interrupt>
[ 235.577073] lock(&ab->base_lock);
[ 235.577074]
[ 235.577074] *** DEADLOCK ***
[ 235.577074]
[ 235.577075] 3 locks held by kworker/u16:1/98:
[ 235.577076] #0: ffff9655f75b1d48 ((wq_completion)ath11k_qmi_driver_event){+.+.}-{0:0}, at: process_one_work+0x1d3/0x5d0
[ 235.577079] #1: ffffa33cc02f3e70 ((work_completion)(&ab->qmi.event_work)){+.+.}-{0:0}, at: process_one_work+0x1d3/0x5d0
[ 235.577081] #2: ffff9655f75cad50 (&ab->core_lock){+.+.}-{3:3}, at: ath11k_core_qmi_firmware_ready.part.0+0x4e/0x160 [ath11k]
[ 235.577087]
[ 235.577087] stack backtrace:
[ 235.577088] CPU: 3 PID: 98 Comm: kworker/u16:1 Not tainted 5.9.0-rc5-wt-ath+ #196
[ 235.577089] Hardware name: Intel(R) Client Systems NUC8i7HVK/NUC8i7HVB, BIOS HNKBLi70.86A.0049.2018.0801.1601 08/01/2018
[ 235.577095] Workqueue: ath11k_qmi_driver_event ath11k_qmi_driver_event_work [ath11k]
[ 235.577096] Call Trace:
[ 235.577100] dump_stack+0x77/0xa0
[ 235.577102] mark_lock_irq.cold+0x15/0x3c
[ 235.577104] mark_lock+0x1d7/0x540
[ 235.577105] mark_usage+0xc7/0x140
[ 235.577107] __lock_acquire+0x219/0x6e0
[ 235.577108] ? sched_clock_cpu+0xc/0xb0
[ 235.577110] lock_acquire+0xb6/0x270
[ 235.577116] ? ath11k_regd_update+0x28/0x1d0 [ath11k]
[ 235.577118] ? atomic_notifier_chain_register+0x2d/0x40
[ 235.577120] _raw_spin_lock+0x2c/0x70
[ 235.577125] ? ath11k_regd_update+0x28/0x1d0 [ath11k]
[ 235.577130] ath11k_regd_update+0x28/0x1d0 [ath11k]
[ 235.577136] __ath11k_mac_register+0x3fb/0x480 [ath11k]
[ 235.577141] ath11k_mac_register+0x119/0x180 [ath11k]
[ 235.577146] ath11k_core_pdev_create+0x17/0xe0 [ath11k]
[ 235.577150] ath11k_core_qmi_firmware_ready.part.0+0x65/0x160 [ath11k]
[ 235.577155] ath11k_qmi_driver_event_work+0x1c5/0x230 [ath11k]
[ 235.577158] process_one_work+0x265/0x5d0
[ 235.577160] worker_thread+0x49/0x300
[ 235.577161] ? process_one_work+0x5d0/0x5d0
[ 235.577163] kthread+0x135/0x150
[ 235.577164] ? kthread_create_worker_on_cpu+0x60/0x60
[ 235.577166] ret_from_fork+0x22/0x30Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
--- drivers/net/wireless/ath/ath11k/reg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/wireless/ath/ath11k/reg.c +3 -3
@@ -206,7 +206,7 @@ int ath11k_regd_update(struct ath11k *ar, bool init) ab = ar->ab; pdev_id = ar->pdev_idx; -spin_lock (&ab->base_lock); +spin_lock_bh (&ab->base_lock);if (init) {/* Apply the regd received during init through
@@ -227,7 +227,7 @@ int ath11k_regd_update(struct ath11k *ar, bool init)if (!regd) { ret = -EINVAL ; -spin_unlock (&ab->base_lock); +spin_unlock_bh (&ab->base_lock); goto err; }
@@ -238,7 +238,7 @@ int ath11k_regd_update(struct ath11k *ar, bool init)if (regd_copy)ath11k_copy_regd (regd, regd_copy); -spin_unlock (&ab->base_lock); +spin_unlock_bh (&ab->base_lock);if (!regd_copy) { ret = -ENOMEM ;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 132/391 drivers/net/wan/hdlc_fr: Correctly handle special skb->protocol values
In reply to Greg Kroah-HartmanFrom: Xie He <[email protected]>
[ Upstream commit 8306266c1d51aac9aa7aa907fe99032a58c6382c ]
The fr_hard_header function is used to prepend the header to skbs before transmission. It is used in 3 situations:
1) When a control packet is generated internally in this driver;
2) When a user sends an skb on an Ethernet-emulating PVC device;
3) When a user sends an skb on a normal PVC device.
These 3 situations need to be handled differently by fr_hard_header. Different headers should be prepended to the skb in different situations.
Currently fr_hard_header distinguishes these 3 situations using skb->protocol. For situation 1 and 2, a special skb->protocol value will be assigned before calling fr_hard_header, so that it can recognize these 2 situations. All skb->protocol values other than these special ones are treated by fr_hard_header as situation 3.
However, it is possible that in situation 3, the user sends an skb with one of the special skb->protocol values. In this case, fr_hard_header would incorrectly treat it as situation 1 or 2.
This patch tries to solve this issue by using skb->dev instead of skb->protocol to distinguish between these 3 situations. For situation 1, skb->dev would be NULL; for situation 2, skb->dev->type would be ARPHRD_ETHER; and for situation 3, skb->dev->type would be ARPHRD_DLCI.
This way fr_hard_header would be able to distinguish these 3 situations correctly regardless what skb->protocol value the user tries to use in situation 3.
--- drivers/net/wan/hdlc_fr.c | 98 ++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 47 deletions(-)
drivers/net/wan/hdlc_fr.c +51 -47
@@ -273,63 +273,69 @@ static inline struct net_device **get_dev_p(struct pvc_device *pvc,static int fr_hard_header (struct sk_buff **skb_p,u16 dlci) { -u16 head_len;struct sk_buff *skb = *skb_p; -switch (skb->protocol) { -case cpu_to_be16 (NLPID_CCITT_ANSI_LMI ): - head_len =4 ; -skb_push (skb, head_len); - skb->data[3 ] =NLPID_CCITT_ANSI_LMI ; -break ; - -case cpu_to_be16 (NLPID_CISCO_LMI ): - head_len =4 ; -skb_push (skb, head_len); - skb->data[3 ] =NLPID_CISCO_LMI ; -break ; - -case cpu_to_be16 (ETH_P_IP ): - head_len =4 ; -skb_push (skb, head_len); - skb->data[3 ] =NLPID_IP ; -break ; - -case cpu_to_be16 (ETH_P_IPV6 ): - head_len =4 ; -skb_push (skb, head_len); - skb->data[3 ] =NLPID_IPV6 ; -break ; - -case cpu_to_be16 (ETH_P_802_3 ): - head_len =10 ; -if (skb_headroom (skb) < head_len) { -struct sk_buff *skb2 =skb_realloc_headroom (skb, - head_len); +if (!skb->dev) {/* Control packets */ +switch (dlci) { +case LMI_CCITT_ANSI_DLCI : +skb_push (skb,4 ); + skb->data[3 ] =NLPID_CCITT_ANSI_LMI ; +break ; + +case LMI_CISCO_DLCI : +skb_push (skb,4 ); + skb->data[3 ] =NLPID_CISCO_LMI ; +break ; + +default : +return -EINVAL ; + } + + }else if (skb->dev->type ==ARPHRD_DLCI ) { +switch (skb->protocol) { +case htons (ETH_P_IP ): +skb_push (skb,4 ); + skb->data[3 ] =NLPID_IP ; +break ; + +case htons (ETH_P_IPV6 ): +skb_push (skb,4 ); + skb->data[3 ] =NLPID_IPV6 ; +break ; + +default : +skb_push (skb,10 ); + skb->data[3 ] =FR_PAD ; + skb->data[4 ] =NLPID_SNAP ; +/* OUI 00-00-00 indicates an Ethertype follows */ + skb->data[5 ] =0x00 ; + skb->data[6 ] =0x00 ; + skb->data[7 ] =0x00 ; +/* This should be an Ethertype: */ + *(__be16 *)(skb->data +8 ) = skb->protocol; + } + + }else if (skb->dev->type ==ARPHRD_ETHER ) { +if (skb_headroom (skb) <10 ) { +struct sk_buff *skb2 =skb_realloc_headroom (skb,10 );if (!skb2)return -ENOBUFS ;dev_kfree_skb (skb); skb = *skb_p = skb2; } -skb_push (skb, head_len); +skb_push (skb,10 ); skb->data[3 ] =FR_PAD ; skb->data[4 ] =NLPID_SNAP ; - skb->data[5 ] =FR_PAD ; +/* OUI 00-80-C2 stands for the 802.1 organization */ + skb->data[5 ] =0x00 ; skb->data[6 ] =0x80 ; skb->data[7 ] =0xC2 ; +/* PID 00-07 stands for Ethernet frames without FCS */ skb->data[8 ] =0x00 ; - skb->data[9 ] =0x07 ;/* bridged Ethernet frame w/out FCS */ -break ; + skb->data[9 ] =0x07 ; -default : - head_len =10 ; -skb_push (skb, head_len); - skb->data[3 ] =FR_PAD ; - skb->data[4 ] =NLPID_SNAP ; - skb->data[5 ] =FR_PAD ; - skb->data[6 ] =FR_PAD ; - skb->data[7 ] =FR_PAD ; - *(__be16 *)(skb->data +8 ) = skb->protocol; + }else { +return -EINVAL ; }dlci_to_q922 (skb->data, dlci);
@@ -425,8 +431,8 @@ static netdev_tx_t pvc_xmit(struct sk_buff *skb, struct net_device *dev)skb_put (skb, pad);memset (skb->data + len,0 , pad); } - skb->protocol =cpu_to_be16 (ETH_P_802_3 ); } + skb->dev = dev;if (!fr_hard_header (&skb, pvc->dlci)) { dev->stats.tx_bytes += skb->len; dev->stats.tx_packets++;
@@ -494,10 +500,8 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)memset (skb->data,0 , len);skb_reserve (skb,4 );if (lmi ==LMI_CISCO ) { - skb->protocol =cpu_to_be16 (NLPID_CISCO_LMI );fr_hard_header (&skb,LMI_CISCO_DLCI ); }else { - skb->protocol =cpu_to_be16 (NLPID_CCITT_ANSI_LMI );fr_hard_header (&skb,LMI_CCITT_ANSI_DLCI ); } data =skb_tail_pointer (skb);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 133/391 usb: dwc3: core: do not queue work if dr_mode is not USB_DR_MODE_OTG
In reply to Greg Kroah-HartmanFrom: Li Jun <[email protected]>
[ Upstream commit dc336b19e82d0454ea60270cd18fbb4749e162f6 ]
Do not try to queue a drd work if dr_mode is not USB_DR_MODE_OTG because the work is not inited, this may be triggered by user try to change mode file of debugfs on a single role port, which will cause below kernel dump:
[ 60.115529] ------------[ cut here ]------------ [ 60.120166] WARNING: CPU: 1 PID: 627 at kernel/workqueue.c:1473 __queue_work+0x46c/0x520 [ 60.128254] Modules linked in: [ 60.131313] CPU: 1 PID: 627 Comm: sh Not tainted 5.7.0-rc4-00022-g914a586-dirty #135 [ 60.139054] Hardware name: NXP i.MX8MQ EVK (DT) [ 60.143585] pstate: a0000085 (NzCv daIf -PAN -UAO) [ 60.148376] pc : __queue_work+0x46c/0x520 [ 60.152385] lr : __queue_work+0x314/0x520 [ 60.156393] sp : ffff8000124ebc40 [ 60.159705] x29: ffff8000124ebc40 x28: ffff800011808018 [ 60.165018] x27: ffff800011819ef8 x26: ffff800011d39980 [ 60.170331] x25: ffff800011808018 x24: 0000000000000100 [ 60.175643] x23: 0000000000000013 x22: 0000000000000001 [ 60.180955] x21: ffff0000b7c08e00 x20: ffff0000b6c31080 [ 60.186267] x19: ffff0000bb99bc00 x18: 0000000000000000 [ 60.191579] x17: 0000000000000000 x16: 0000000000000000 [ 60.196891] x15: 0000000000000000 x14: 0000000000000000 [ 60.202202] x13: 0000000000000000 x12: 0000000000000000 [ 60.207515] x11: 0000000000000000 x10: 0000000000000040 [ 60.212827] x9 : ffff800011d55460 x8 : ffff800011d55458 [ 60.218138] x7 : ffff0000b7800028 x6 : 0000000000000000 [ 60.223450] x5 : ffff0000b7800000 x4 : 0000000000000000 [ 60.228762] x3 : ffff0000bb997cc0 x2 : 0000000000000001 [ 60.234074] x1 : 0000000000000000 x0 : ffff0000b6c31088 [ 60.239386] Call trace: [ 60.241834] __queue_work+0x46c/0x520 [ 60.245496] queue_work_on+0x6c/0x90 [ 60.249075] dwc3_set_mode+0x48/0x58 [ 60.252651] dwc3_mode_write+0xf8/0x150 [ 60.256489] full_proxy_write+0x5c/0xa8 [ 60.260327] __vfs_write+0x18/0x40 [ 60.263729] vfs_write+0xdc/0x1c8 [ 60.267045] ksys_write+0x68/0xf0 [ 60.270360] __arm64_sys_write+0x18/0x20 [ 60.274286] el0_svc_common.constprop.0+0x68/0x160 [ 60.279077] do_el0_svc+0x20/0x80 [ 60.282394] el0_sync_handler+0x10c/0x178 [ 60.286403] el0_sync+0x140/0x180 [ 60.289716] ---[ end trace 70b155582e2b7988 ]---
--- drivers/usb/dwc3/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/usb/dwc3/core.c +3 -3
@@ -121,9 +121,6 @@ static void __dwc3_set_mode(struct work_struct *work)int ret;u32 reg; -if (dwc->dr_mode !=USB_DR_MODE_OTG ) -return ; -pm_runtime_get_sync (dwc->dev);if (dwc->current_dr_role ==DWC3_GCTL_PRTCAP_OTG )
@@ -209,6 +206,9 @@ void dwc3_set_mode(struct dwc3 *dwc, u32 mode) {unsigned long flags; +if (dwc->dr_mode !=USB_DR_MODE_OTG ) +return ; +spin_lock_irqsave (&dwc->lock, flags); dwc->desired_dr_role = mode;spin_unlock_irqrestore (&dwc->lock, flags);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 134/391 bus: mhi: core: Abort suspends due to outgoing pending packets
In reply to Greg Kroah-HartmanFrom: Bhaumik Bhatt <[email protected]>
[ Upstream commit 515847c557dd33167be86cb429fc0674a331bc88 ]
Add the missing check to abort suspends if a client driver has pending outgoing packets to send to the device. This allows better utilization of the MHI bus wherein clients on the host are not left waiting for longer suspend or resume cycles to finish for data transfers.
--- drivers/bus/mhi/core/pm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/bus/mhi/core/pm.c +4 -2
@@ -686,7 +686,8 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl)return -EIO ;/* Return busy if there are any pending resources */ -if (atomic_read (&mhi_cntrl->dev_wake)) +if (atomic_read (&mhi_cntrl->dev_wake) || +atomic_read (&mhi_cntrl->pending_pkts))return -EBUSY ;/* Take MHI out of M2 state */
@@ -712,7 +713,8 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl)write_lock_irq (&mhi_cntrl->pm_lock); -if (atomic_read (&mhi_cntrl->dev_wake)) { +if (atomic_read (&mhi_cntrl->dev_wake) || +atomic_read (&mhi_cntrl->pending_pkts)) {write_unlock_irq (&mhi_cntrl->pm_lock);return -EBUSY ; }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 135/391 bus/fsl_mc: Do not rely on caller to provide non NULL mc_io
In reply to Greg Kroah-HartmanFrom: Diana Craciun <[email protected]>
[ Upstream commit 5026cf605143e764e1785bbf9158559d17f8d260 ]
Before destroying the mc_io, check first that it was allocated.
--- drivers/bus/fsl-mc/mc-io.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/bus/fsl-mc/mc-io.c +6 -1
@@ -129,7 +129,12 @@ error_destroy_mc_io:*/ void fsl_destroy_mc_io (struct fsl_mc_io *mc_io) { -struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev; +struct fsl_mc_device *dpmcp_dev; + +if (!mc_io) +return ; + + dpmcp_dev = mc_io->dpmcp_dev;if (dpmcp_dev)fsl_mc_io_unset_dpmcp (mc_io);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 136/391 ACPI: HMAT: Fix handling of changes from ACPI 6.2 to ACPI 6.3
In reply to Greg Kroah-HartmanFrom: Jonathan Cameron <[email protected]>
[ Upstream commit 2c5b9bde95c96942f2873cea6ef383c02800e4a8 ]
In ACPI 6.3, the Memory Proximity Domain Attributes Structure changed substantially. One of those changes was that the flag for "Memory Proximity Domain field is valid" was deprecated.
This was because the field "Proximity Domain for the Memory" became a required field and hence having a validity flag makes no sense.
So the correct logic is to always assume the field is there. Current code assumes it never is.
--- drivers/acpi/numa/hmat.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/acpi/numa/hmat.c +2 -1
@@ -424,7 +424,8 @@ static int __init hmat_parse_proximity_domain(union acpi_subtable_headers *headepr_info ("HMAT: Memory Flags:%04x Processor Domain:%u Memory Domain:%u\n" , p->flags, p->processor_PD, p->memory_PD); -if (p->flags &ACPI_HMAT_MEMORY_PD_VALID && hmat_revision ==1 ) { +if ((hmat_revision ==1 && p->flags &ACPI_HMAT_MEMORY_PD_VALID ) || + hmat_revision >1 ) { target =find_mem_target (p->memory_PD);if (!target) {pr_debug ("HMAT: Memory Domain missing from SRAT\n" );
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 137/391 power: supply: test_power: add missing newlines when printing parameters by sysfs
In reply to Greg Kroah-HartmanFrom: Xiongfeng Wang <[email protected]>
[ Upstream commit c07fa6c1631333f02750cf59f22b615d768b4d8f ]
When I cat some module parameters by sysfs, it displays as follows. It's better to add a newline for easy reading.
root@syzkaller:~# cd /sys/module/test_power/parameters/ root@syzkaller:/sys/module/test_power/parameters# cat ac_online onroot@syzkaller:/sys/module/test_power/parameters# cat battery_present trueroot@syzkaller:/sys/module/test_power/parameters# cat battery_health goodroot@syzkaller:/sys/module/test_power/parameters# cat battery_status dischargingroot@syzkaller:/sys/module/test_power/parameters# cat battery_technology LIONroot@syzkaller:/sys/module/test_power/parameters# cat usb_online onroot@syzkaller:/sys/module/test_power/parameters#
--- drivers/power/supply/test_power.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/power/supply/test_power.c +6 -0
@@ -353,6 +353,7 @@ static int param_set_ac_online(const char *key, const struct kernel_param *kp)static int param_get_ac_online (char *buffer,const struct kernel_param *kp) {strcpy (buffer,map_get_key (map_ac_online, ac_online,"unknown" )); +strcat (buffer,"\n" );return strlen (buffer); }
@@ -366,6 +367,7 @@ static int param_set_usb_online(const char *key, const struct kernel_param *kp)static int param_get_usb_online (char *buffer,const struct kernel_param *kp) {strcpy (buffer,map_get_key (map_ac_online, usb_online,"unknown" )); +strcat (buffer,"\n" );return strlen (buffer); }
@@ -380,6 +382,7 @@ static int param_set_battery_status(const char *key,static int param_get_battery_status (char *buffer,const struct kernel_param *kp) {strcpy (buffer,map_get_key (map_status, battery_status,"unknown" )); +strcat (buffer,"\n" );return strlen (buffer); }
@@ -394,6 +397,7 @@ static int param_set_battery_health(const char *key,static int param_get_battery_health (char *buffer,const struct kernel_param *kp) {strcpy (buffer,map_get_key (map_health, battery_health,"unknown" )); +strcat (buffer,"\n" );return strlen (buffer); }
@@ -409,6 +413,7 @@ static int param_get_battery_present(char *buffer, const struct kernel_param *kp) {strcpy (buffer,map_get_key (map_present, battery_present,"unknown" )); +strcat (buffer,"\n" );return strlen (buffer); }
@@ -426,6 +431,7 @@ static int param_get_battery_technology(char *buffer, {strcpy (buffer,map_get_key (map_technology, battery_technology,"unknown" )); +strcat (buffer,"\n" );return strlen (buffer); }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 138/391 drm/amd/display: HDMI remote sink need mode validation for Linux
In reply to Greg Kroah-HartmanFrom: Fangzhi Zuo <[email protected]>
[ Upstream commit 95d620adb48f7728e67d82f56f756e8d451cf8d2 ]
[Why]
Currently mode validation is bypassed if remote sink exists. That leads to mode set issue when a BW bottle neck exists in the link path, e.g., a DP-to-HDMI converter that only supports HDMI 1.4.
Any invalid mode passed to Linux user space will cause the modeset failure due to limitation of Linux user space implementation.
[How]
Mode validation is skipped only if in edid override. For real remote sink, clock limit check should be done for HDMI remote sink.
Have HDMI related remote sink going through mode validation to elimiate modes which pixel clock exceeds BW limitation.
--- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/amd/display/dc/core/dc_link.c +1 -1
@@ -2441,7 +2441,7 @@ enum dc_status dc_link_validate_mode_timing(/* A hack to avoid failing any modes for EDID override feature on * topology change such as lower quality cable for DP or different dongle */ -if (link->remote_sinks[0 ]) +if (link->remote_sinks[0 ] && link->remote_sinks[0 ]->sink_signal ==SIGNAL_TYPE_VIRTUAL )return DC_OK ;/* Passive Dongle */
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 139/391 drm/amd/display: Avoid set zero in the requested clk
In reply to Greg Kroah-HartmanFrom: Rodrigo Siqueira <[email protected]>
[ Upstream commit 2f8be0e516803cc3fd87c1671247896571a5a8fb ]
[Why]
Sometimes CRTCs can be disabled due to display unplugging or temporarily transition in the userspace; in these circumstances, DCE tries to set the minimum clock threshold. When we have this situation, the function bw_calcs is invoked with number_of_displays set to zero, making DCE set dispclk_khz and sclk_khz to zero. For these reasons, we have seen some ATOM bios errors that look like:
[drm:atom_op_jump [amdgpu]] *ERROR* atombios stuck in loop for more than 5secs aborting
[drm:amdgpu_atom_execute_table_locked [amdgpu]] *ERROR* atombios stuck executing EA8A (len 761, WS 0, PS 0) @ 0xEABA
[How]
This error happens due to an attempt to optimize the bandwidth using the sclk, and the dispclk clock set to zero. Technically we handle this in the function dce112_set_clock, but we are not considering the case that this value is set to zero. This commit fixes this issue by ensuring that we never set a minimum value below the minimum clock threshold.
--- drivers/gpu/drm/amd/display/dc/clk_mgr/dce112/dce112_clk_mgr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/gpu/drm/amd/display/dc/clk_mgr/dce112/dce112_clk_mgr.c +1 -2
@@ -79,8 +79,7 @@ int dce112_set_clock(struct clk_mgr *clk_mgr_base, int requested_clk_khz)memset (&dce_clk_params,0 ,sizeof (dce_clk_params));/* Make sure requested clock isn't lower than minimum threshold*/ -if (requested_clk_khz >0 ) - requested_clk_khz =max (requested_clk_khz, + requested_clk_khz =max (requested_clk_khz, clk_mgr_dce->base.dentist_vco_freq_khz /62 ); dce_clk_params.target_clock_frequency = requested_clk_khz;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 140/391 ARC: [dts] fix the errors detected by dtbs_check
In reply to Greg Kroah-HartmanFrom: Zhen Lei <[email protected]>
[ Upstream commit 05b1be68c4d6d76970025e6139bfd735c2256ee5 ]
xxx/arc/boot/dts/axs101.dt.yaml: dw-apb-ictl@e0012000: $nodename:0: \
'dw-apb-ictl@e0012000' does not match '^interrupt-controller(@[0-9a-f,]+)*$'
From schema: xxx/interrupt-controller/snps,dw-apb-ictl.yaml
The node name of the interrupt controller must start with "interrupt-controller" instead of "dw-apb-ictl".
--- arch/arc/boot/dts/axc001.dtsi | 2 +- arch/arc/boot/dts/axc003.dtsi | 2 +- arch/arc/boot/dts/axc003_idu.dtsi | 2 +- arch/arc/boot/dts/vdk_axc003.dtsi | 2 +- arch/arc/boot/dts/vdk_axc003_idu.dtsi | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-)
arch/arc/boot/dts/axc001.dtsi +1 -1
@@ -91,7 +91,7 @@ * avoid duplicating the MB dtsi file given that IRQ from * this intc to cpu intc are different for axs101 and axs103 */ - mb_intc: dw-apb-ictl@e0012000 { + mb_intc: interrupt-controller@e0012000 { #interrupt-cells = <1>; compatible = "snps,dw-apb-ictl"; reg = < 0x0 0xe0012000 0x0 0x200 >;
arch/arc/boot/dts/axc003.dtsi +1 -1
@@ -129,7 +129,7 @@ * avoid duplicating the MB dtsi file given that IRQ from * this intc to cpu intc are different for axs101 and axs103 */ - mb_intc: dw-apb-ictl@e0012000 { + mb_intc: interrupt-controller@e0012000 { #interrupt-cells = <1>; compatible = "snps,dw-apb-ictl"; reg = < 0x0 0xe0012000 0x0 0x200 >;
arch/arc/boot/dts/axc003_idu.dtsi +1 -1
@@ -135,7 +135,7 @@ * avoid duplicating the MB dtsi file given that IRQ from * this intc to cpu intc are different for axs101 and axs103 */ - mb_intc: dw-apb-ictl@e0012000 { + mb_intc: interrupt-controller@e0012000 { #interrupt-cells = <1>; compatible = "snps,dw-apb-ictl"; reg = < 0x0 0xe0012000 0x0 0x200 >;
arch/arc/boot/dts/vdk_axc003.dtsi +1 -1
@@ -46,7 +46,7 @@ }; - mb_intc: dw-apb-ictl@e0012000 { + mb_intc: interrupt-controller@e0012000 { #interrupt-cells = <1>; compatible = "snps,dw-apb-ictl"; reg = < 0xe0012000 0x200 >;
arch/arc/boot/dts/vdk_axc003_idu.dtsi +1 -1
@@ -54,7 +54,7 @@ }; - mb_intc: dw-apb-ictl@e0012000 { + mb_intc: interrupt-controller@e0012000 { #interrupt-cells = <1>; compatible = "snps,dw-apb-ictl"; reg = < 0xe0012000 0x200 >;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 141/391 block: Consider only dispatched requests for inflight statistic
In reply to Greg Kroah-HartmanFrom: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit a926c7afffcc0f2e35e6acbccb16921bacf34617 ]
According to Documentation/block/stat.rst, inflight should not include I/O requests that are in the queue but not yet dispatched to the device, but blk-mq identifies as inflight any request that has a tag allocated, which, for queues without elevator, happens at request allocation time and before it is queued in the ctx (default case in blk_mq_submit_bio).
In addition, current behavior is different for queues with elevator from queues without it, since for the former the driver tag is allocated at dispatch time. A more precise approach would be to only consider requests with state MQ_RQ_IN_FLIGHT.
This effectively reverts commit 6131837b1de6 ("blk-mq: count allocated but not started requests in iostats inflight") to consolidate blk-mq behavior with itself (elevator case) and with original documentation, but it differs from the behavior used by the legacy path.
This version differs from v1 by using blk_mq_rq_state to access the state attribute. Avoid using blk_mq_request_started, which was suggested, since we don't want to include MQ_RQ_COMPLETE.
--- block/blk-mq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
block/blk-mq.c +1 -1
@@ -105,7 +105,7 @@ static bool blk_mq_check_inflight(struct blk_mq_hw_ctx *hctx, {struct mq_inflight *mi = priv; -if (rq->part == mi->part) +if (rq->part == mi->part &&blk_mq_rq_state (rq) ==MQ_RQ_IN_FLIGHT ) mi->inflight[rq_data_dir (rq)]++;return true;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 142/391 btrfs: fix replace of seed device
In reply to Greg Kroah-HartmanFrom: Anand Jain <[email protected]>
[ Upstream commit c6a5d954950c5031444173ad2195efc163afcac9 ]
If you replace a seed device in a sprouted fs, it appears to have successfully replaced the seed device, but if you look closely, it didn't. Here is an example.
$ mkfs.btrfs /dev/sda $ btrfstune -S1 /dev/sda $ mount /dev/sda /btrfs $ btrfs device add /dev/sdb /btrfs $ umount /btrfs $ btrfs device scan --forget $ mount -o device=/dev/sda /dev/sdb /btrfs $ btrfs replace start -f /dev/sda /dev/sdc /btrfs $ echo $? 0
BTRFS info (device sdb): dev_replace from /dev/sda (devid 1) to /dev/sdc started BTRFS info (device sdb): dev_replace from /dev/sda (devid 1) to /dev/sdc finished
$ btrfs fi show Label: none uuid: ab2c88b7-be81-4a7e-9849-c3666e7f9f4f Total devices 2 FS bytes used 256.00KiB devid 1 size 3.00GiB used 520.00MiB path /dev/sdc devid 2 size 3.00GiB used 896.00MiB path /dev/sdb
Label: none uuid: 10bd3202-0415-43af-96a8-d5409f310a7e
Total devices 1 FS bytes used 128.00KiB
devid 1 size 3.00GiB used 536.00MiB path /dev/sda
So as per the replace start command and kernel log replace was successful. Now let's try to clean mount.
$ umount /btrfs $ btrfs device scan --forget
$ mount -o device=/dev/sdc /dev/sdb /btrfs mount: /btrfs: wrong fs type, bad option, bad superblock on /dev/sdb, missing codepage or helper program, or other error.
[ 636.157517] BTRFS error (device sdc): failed to read chunk tree: -2 [ 636.180177] BTRFS error (device sdc): open_ctree failed
That's because per dev items it is still looking for the original seed device.
$ btrfs inspect-internal dump-tree -d /dev/sdb
item 0 key (DEV_ITEMS DEV_ITEM 1) itemoff 16185 itemsize 98 devid 1 total_bytes 3221225472 bytes_used 545259520 io_align 4096 io_width 4096 sector_size 4096 type 0 generation 6 start_offset 0 dev_group 0 seek_speed 0 bandwidth 0 uuid 59368f50-9af2-4b17-91da-8a783cc418d4 <--- seed uuid fsid 10bd3202-0415-43af-96a8-d5409f310a7e <--- seed fsid item 1 key (DEV_ITEMS DEV_ITEM 2) itemoff 16087 itemsize 98 devid 2 total_bytes 3221225472 bytes_used 939524096 io_align 4096 io_width 4096 sector_size 4096 type 0 generation 0 start_offset 0 dev_group 0 seek_speed 0 bandwidth 0 uuid 56a0a6bc-4630-4998-8daf-3c3030c4256a <- sprout uuid fsid ab2c88b7-be81-4a7e-9849-c3666e7f9f4f <- sprout fsid
But the replaced target has the following uuid+fsid in its superblock which doesn't match with the expected uuid+fsid in its devitem.
$ btrfs in dump-super /dev/sdc | egrep '^generation|dev_item.uuid|dev_item.fsid|devid' generation 20 dev_item.uuid 59368f50-9af2-4b17-91da-8a783cc418d4 dev_item.fsid ab2c88b7-be81-4a7e-9849-c3666e7f9f4f [match] dev_item.devid 1
So if you provide the original seed device the mount shall be successful. Which so long happening in the test case btrfs/163.
$ btrfs device scan --forget $ mount -o device=/dev/sda /dev/sdb /btrfs
Fix in this patch:
If a seed is not sprouted then there is no replacement of it, because of its read-only filesystem with a read-only device. Similarly, in the case of a sprouted filesystem, the seed device is still read only. So, mark it as you can't replace a seed device, you can only add a new device and then delete the seed device. If replace is attempted then returns -EINVAL.
--- fs/btrfs/dev-replace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/btrfs/dev-replace.c +1 -1
@@ -230,7 +230,7 @@ static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,int ret =0 ; *device_out =NULL ; -if (fs_info->fs_devices->seeding) { +if (srcdev->fs_devices->seeding) {btrfs_err (fs_info,"the filesystem is a seed filesystem!" );return -EINVAL ; }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 143/391 md/bitmap: md_bitmap_get_counter returns wrong blocks
In reply to Greg Kroah-HartmanFrom: Zhao Heming <[email protected]>
[ Upstream commit d837f7277f56e70d82b3a4a037d744854e62f387 ]
md_bitmap_get_counter() has code:
```
if (bitmap->bp[page].hijacked ||
bitmap->bp[page].map == NULL)
csize = ((sector_t)1) << (bitmap->chunkshift +
PAGE_COUNTER_SHIFT - 1);
```The minus 1 is wrong, this branch should report 2048 bits of space. With "-1" action, this only report 1024 bit of space.
This bug code returns wrong blocks, but it doesn't inflence bitmap logic:
1. Most callers focus this function return value (the counter of offset), not the parameter blocks.
2. The bug is only triggered when hijacked is true or map is NULL. the hijacked true condition is very rare.
the "map == null" only true when array is creating or resizing.
3. Even the caller gets wrong blocks, current code makes caller just to call md_bitmap_get_counter() one more time.
--- drivers/md/md-bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/md/md-bitmap.c +1 -1
@@ -1367,7 +1367,7 @@ __acquires(bitmap->lock)if (bitmap->bp[page].hijacked || bitmap->bp[page].map ==NULL ) csize = ((sector_t )1 ) << (bitmap->chunkshift + -PAGE_COUNTER_SHIFT -1 ); +PAGE_COUNTER_SHIFT );else csize = ((sector_t )1 ) << bitmap->chunkshift; *blocks = csize - (offset & (csize -1 ));
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 144/391 f2fs: fix to set SBI_NEED_FSCK flag for inconsistent inode
In reply to Greg Kroah-HartmanFrom: Chao Yu <[email protected]>
[ Upstream commit d662fad143c0470ad7f46ea7b02da539f613d7d7 ]
If compressed inode has inconsistent fields on i_compress_algorithm, i_compr_blocks and i_log_cluster_size, we missed to set SBI_NEED_FSCK to notice fsck to repair the inode, fix it.
--- fs/f2fs/inode.c | 3 +++ 1 file changed, 3 insertions(+)
fs/f2fs/inode.c +3 -0
@@ -299,6 +299,7 @@ static bool sanity_check_inode(struct inode *inode, struct page *node_page) F2FS_FITS_IN_INODE(ri, fi->i_extra_isize, i_log_cluster_size)) {if (ri->i_compress_algorithm >=COMPRESS_MAX ) { +set_sbi_flag (sbi,SBI_NEED_FSCK ); f2fs_warn(sbi, "%s: inode (ino=%lx) has unsupported " "compress algorithm: %u, run fsck to fix", __func__, inode->i_ino,
@@ -307,6 +308,7 @@ static bool sanity_check_inode(struct inode *inode, struct page *node_page) }if (le64_to_cpu (ri->i_compr_blocks) >SECTOR_TO_BLOCK (inode->i_blocks)) { +set_sbi_flag (sbi,SBI_NEED_FSCK ); f2fs_warn(sbi, "%s: inode (ino=%lx) has inconsistent " "i_compr_blocks:%llu, i_blocks:%llu, run fsck to fix", __func__, inode->i_ino,
@@ -316,6 +318,7 @@ static bool sanity_check_inode(struct inode *inode, struct page *node_page) }if (ri->i_log_cluster_size <MIN_COMPRESS_LOG_SIZE || ri->i_log_cluster_size >MAX_COMPRESS_LOG_SIZE ) { +set_sbi_flag (sbi,SBI_NEED_FSCK ); f2fs_warn(sbi, "%s: inode (ino=%lx) has unsupported " "log cluster size: %u, run fsck to fix", __func__, inode->i_ino,
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 145/391 bnxt_en: Log unknown link speed appropriately.
In reply to Greg Kroah-HartmanFrom: Michael Chan <[email protected]>
[ Upstream commit 8eddb3e7ce124dd6375d3664f1aae13873318b0f ]
If the VF virtual link is set to always enabled, the speed may be unknown when the physical link is down. The driver currently logs the link speed as 4294967295 Mbps which is SPEED_UNKNOWN. Modify the link up log message as "speed unknown" which makes more sense.
--- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/net/ethernet/broadcom/bnxt/bnxt.c +5 -1
@@ -8735,6 +8735,11 @@ static void bnxt_report_link(struct bnxt *bp)u16 fec;netif_carrier_on (bp->dev); + speed =bnxt_fw_to_ethtool_speed (bp->link_info.link_speed); +if (speed ==SPEED_UNKNOWN ) { +netdev_info (bp->dev,"NIC Link is Up, speed unknown\n" ); +return ; + }if (bp->link_info.duplex ==BNXT_LINK_DUPLEX_FULL ) duplex ="full" ;else
@@ -8747,7 +8752,6 @@ static void bnxt_report_link(struct bnxt *bp) flow_ctrl ="ON - receive" ; else flow_ctrl ="none" ; - speed =bnxt_fw_to_ethtool_speed (bp->link_info.link_speed);netdev_info (bp->dev,"NIC Link is Up, %u Mbps %s duplex, Flow control: %s\n" , speed, duplex, flow_ctrl);if (bp->flags &BNXT_FLAG_EEE_CAP )
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 146/391 rpmsg: glink: Use complete_all for open states
In reply to Greg Kroah-HartmanFrom: Chris Lew <[email protected]>
[ Upstream commit 4fcdaf6e28d11e2f3820d54dd23cd12a47ddd44e ]
The open_req and open_ack completion variables are the state variables to represet a remote channel as open. Use complete_all so there are no races with waiters and using completion_done.
--- drivers/rpmsg/qcom_glink_native.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/rpmsg/qcom_glink_native.c +3 -3
@@ -970,7 +970,7 @@ static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid)return -EINVAL ; } -complete (&channel->open_ack); +complete_all (&channel->open_ack);return 0 ; }
@@ -1178,7 +1178,7 @@ static int qcom_glink_announce_create(struct rpmsg_device *rpdev)__be32 *val = defaults;int size; -if (glink->intentless) +if (glink->intentless || !completion_done (&channel->open_ack))return 0 ; prop =of_find_property (np,"qcom,intents" ,NULL );
@@ -1413,7 +1413,7 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid, channel->rcid = ret;spin_unlock_irqrestore (&glink->idr_lock, flags); -complete (&channel->open_req); +complete_all (&channel->open_req);if (create_device) { rpdev =kzalloc (sizeof (*rpdev),GFP_KERNEL );
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 147/391 PCI/ACPI: Add Ampere Altra SOC MCFG quirk
In reply to Greg Kroah-HartmanFrom: Tuan Phan <[email protected]>
[ Upstream commit 877c1a5f79c6984bbe3f2924234c08e2f4f1acd5 ]
Ampere Altra SOC supports only 32-bit ECAM reads. Add an MCFG quirk for the platform.
--- drivers/acpi/pci_mcfg.c | 20 ++++++++++++++++++++ drivers/pci/ecam.c | 10 ++++++++++ include/linux/pci-ecam.h | 1 + 3 files changed, 31 insertions(+)
drivers/acpi/pci_mcfg.c +20 -0
@@ -142,6 +142,26 @@ static struct mcfg_fixup mcfg_quirks[] = {XGENE_V2_ECAM_MCFG (4 ,0 ),XGENE_V2_ECAM_MCFG (4 ,1 ),XGENE_V2_ECAM_MCFG (4 ,2 ), + +#define ALTRA_ECAM_QUIRK(rev, seg) \ + { "Ampere", "Altra ", rev, seg, MCFG_BUS_ANY, &pci_32b_read_ops } + +ALTRA_ECAM_QUIRK (1 ,0 ), +ALTRA_ECAM_QUIRK (1 ,1 ), +ALTRA_ECAM_QUIRK (1 ,2 ), +ALTRA_ECAM_QUIRK (1 ,3 ), +ALTRA_ECAM_QUIRK (1 ,4 ), +ALTRA_ECAM_QUIRK (1 ,5 ), +ALTRA_ECAM_QUIRK (1 ,6 ), +ALTRA_ECAM_QUIRK (1 ,7 ), +ALTRA_ECAM_QUIRK (1 ,8 ), +ALTRA_ECAM_QUIRK (1 ,9 ), +ALTRA_ECAM_QUIRK (1 ,10 ), +ALTRA_ECAM_QUIRK (1 ,11 ), +ALTRA_ECAM_QUIRK (1 ,12 ), +ALTRA_ECAM_QUIRK (1 ,13 ), +ALTRA_ECAM_QUIRK (1 ,14 ), + ALTRA_ECAM_QUIRK(1, 15), };static char mcfg_oem_id[ACPI_OEM_ID_SIZE ];
drivers/pci/ecam.c +10 -0
@@ -168,4 +168,14 @@ const struct pci_ecam_ops pci_32b_ops = { .write = pci_generic_config_write32, } }; + +/* ECAM ops for 32-bit read only (non-compliant) */ +const struct pci_ecam_ops pci_32b_read_ops = { + .bus_shift =20 , + .pci_ops = { + .map_bus = pci_ecam_map_bus, + .read = pci_generic_config_read32, + .write = pci_generic_config_write, + } +};#endif
include/linux/pci-ecam.h +1 -0
@@ -51,6 +51,7 @@ extern const struct pci_ecam_ops pci_generic_ecam_ops;#if defined(CONFIG_ACPI ) && defined(CONFIG_PCI_QUIRKS )extern const struct pci_ecam_ops pci_32b_ops;/* 32-bit accesses only */ +extern const struct pci_ecam_ops pci_32b_read_ops;/* 32-bit read only */ extern const struct pci_ecam_ops hisi_pcie_ops;/* HiSilicon */ extern const struct pci_ecam_ops thunder_pem_ecam_ops;/* Cavium ThunderX 1.x & 2.x */ extern const struct pci_ecam_ops pci_thunder_ecam_ops;/* Cavium ThunderX 1.x */
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 148/391 clk: ti: clockdomain: fix static checker warning
In reply to Greg Kroah-HartmanFrom: Tero Kristo <[email protected]>
[ Upstream commit b7a7943fe291b983b104bcbd2f16e8e896f56590 ]
Fix a memory leak induced by not calling clk_put after doing of_clk_get.
--- drivers/clk/ti/clockdomain.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/clk/ti/clockdomain.c +2 -0
@@ -148,10 +148,12 @@ static void __init of_ti_clockdomain_setup(struct device_node *node)if (!omap2_clk_is_hw_omap (clk_hw)) {pr_warn ("can't setup clkdm for basic clk %s\n" ,__clk_get_name (clk)); +clk_put (clk);continue ; }to_clk_hw_omap (clk_hw)->clkdm_name = clkdm_name;omap2_init_clk_clkdm (clk_hw); +clk_put (clk); } }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 149/391 nfsd: rename delegation related tracepoints to make them less confusing
In reply to Greg Kroah-HartmanFrom: Hou Tao <[email protected]>
[ Upstream commit 3caf91757ced158e6c4a44d8b105bd7b3e1767d8 ]
Now when a read delegation is given, two delegation related traces will be printed:
nfsd_deleg_open: client 5f45b854:e6058001 stateid 00000030:00000001
nfsd_deleg_none: client 5f45b854:e6058001 stateid 0000002f:00000001Although the intention is to let developers know two stateid are returned, the traces are confusing about whether or not a read delegation is handled out. So renaming trace_nfsd_deleg_none() to trace_nfsd_open() and trace_nfsd_deleg_open() to trace_nfsd_deleg_read() to make the intension clearer.
The patched traces will be:
nfsd_deleg_read: client 5f48a967:b55b21cd stateid 00000003:00000001
nfsd_open: client 5f48a967:b55b21cd stateid 00000002:00000001--- fs/nfsd/nfs4state.c | 4 ++-- fs/nfsd/trace.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
fs/nfsd/nfs4state.c +2 -2
@@ -5126,7 +5126,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open,memcpy (&open->op_delegate_stateid, &dp->dl_stid.sc_stateid,sizeof (dp->dl_stid.sc_stateid)); -trace_nfsd_deleg_open (&dp->dl_stid.sc_stateid); +trace_nfsd_deleg_read (&dp->dl_stid.sc_stateid); open->op_delegate_type =NFS4_OPEN_DELEGATE_READ ;nfs4_put_stid (&dp->dl_stid);return ;
@@ -5243,7 +5243,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfnfs4_open_delegation (current_fh, open, stp); nodeleg: status = nfs_ok; -trace_nfsd_deleg_none (&stp->st_stid.sc_stateid); +trace_nfsd_open (&stp->st_stid.sc_stateid); out:/* 4.1 client trying to upgrade/downgrade delegation? */ if (open->op_delegate_type == NFS4_OPEN_DELEGATE_NONE && dp &&
fs/nfsd/trace.h +2 -2
@@ -289,8 +289,8 @@ DEFINE_STATEID_EVENT(layout_recall_done);DEFINE_STATEID_EVENT (layout_recall_fail);DEFINE_STATEID_EVENT (layout_recall_release); -DEFINE_STATEID_EVENT (deleg_open); -DEFINE_STATEID_EVENT (deleg_none); +DEFINE_STATEID_EVENT (open); +DEFINE_STATEID_EVENT (deleg_read);DEFINE_STATEID_EVENT (deleg_break);DEFINE_STATEID_EVENT (deleg_recall);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 150/391 nfsd4: remove check_conflicting_opens warning
In reply to Greg Kroah-HartmanFrom: J. Bruce Fields <[email protected]>
[ Upstream commit 50747dd5e47bde3b7d7f839c84d0d3b554090497 ]
There are actually rare races where this is possible (e.g. if a new open intervenes between the read of i_writecount and the fi_fds).
--- fs/nfsd/nfs4state.c | 1 - 1 file changed, 1 deletion(-)
fs/nfsd/nfs4state.c +0 -1
@@ -4954,7 +4954,6 @@ static int nfsd4_check_conflicting_opens(struct nfs4_client *clp, writes--;if (fp->fi_fds[O_RDWR ]) writes--; -WARN_ON_ONCE (writes <0 );if (writes >0 )return -EAGAIN ;spin_lock (&fp->fi_lock);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 151/391 net: 9p: initialize sun_server.sun_path to have addrs value only when addr is valid
In reply to Greg Kroah-HartmanFrom: Anant Thazhemadam <[email protected]>
[ Upstream commit 7ca1db21ef8e0e6725b4d25deed1ca196f7efb28 ]
In p9_fd_create_unix, checking is performed to see if the addr (passed as an argument) is NULL or not.
However, no check is performed to see if addr is a valid address, i.e., it doesn't entirely consist of only 0's.
The initialization of sun_server.sun_path to be equal to this faulty addr value leads to an uninitialized variable, as detected by KMSAN. Checking for this (faulty addr) and returning a negative error number appropriately, resolves this issue.
--- net/9p/trans_fd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/9p/trans_fd.c +1 -1
@@ -1023,7 +1023,7 @@ p9_fd_create_unix(struct p9_client *client, const char *addr, char *args) csocket =NULL ; -if (addr ==NULL ) +if (!addr || !strlen (addr))return -EINVAL ;if (strlen (addr) >=UNIX_PATH_MAX ) {
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 152/391 ceph: encode inodes parent/d_name in cap reconnect message
In reply to Greg Kroah-HartmanFrom: Yan, Zheng <[email protected]>
[ Upstream commit a33f6432b3a63a4909dbbb0967f7c9df8ff2de91 ]
Since nautilus, MDS tracks dirfrags whose child inodes have caps in open file table. When MDS recovers, it prefetches all of these dirfrags. This avoids using backtrace to load inodes. But dirfrags prefetch may load lots of useless inodes into cache, and make MDS run out of memory.
Recent MDS adds an option that disables dirfrags prefetch. When dirfrags prefetch is disabled. Recovering MDS only prefetches corresponding dir inodes. Including inodes' parent/d_name in cap reconnect message can help MDS to load inodes into its cache.
--- fs/ceph/mds_client.c | 89 ++++++++++++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 28 deletions(-)
fs/ceph/mds_client.c +61 -28
@@ -3612,6 +3612,39 @@ fail_msg:return err; } +static struct dentry *d_find_primary (struct inode *inode) +{ +struct dentry *alias, *dn =NULL ; + +if (hlist_empty (&inode->i_dentry)) +return NULL ; + +spin_lock (&inode->i_lock); +if (hlist_empty (&inode->i_dentry)) + goto out_unlock; + +if (S_ISDIR (inode->i_mode)) { + alias = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias); +if (!IS_ROOT (alias)) + dn =dget (alias); + goto out_unlock; + } + +hlist_for_each_entry (alias, &inode->i_dentry, d_u.d_alias) { +spin_lock (&alias->d_lock); +if (!d_unhashed (alias) && + (ceph_dentry (alias)->flags &CEPH_DENTRY_PRIMARY_LINK )) { + dn =dget_dlock (alias); + } +spin_unlock (&alias->d_lock); +if (dn) +break ; + } +out_unlock: +spin_unlock (&inode->i_lock); +return dn; +} +/* * Encode information about a cap for a reconnect with the MDS. */
@@ -3625,13 +3658,32 @@ static int reconnect_caps_cb(struct inode *inode, struct ceph_cap *cap,struct ceph_inode_info *ci = cap->ci;struct ceph_reconnect_state *recon_state = arg;struct ceph_pagelist *pagelist = recon_state->pagelist; -int err; +struct dentry *dentry; +char *path; +int pathlen, err; +u64 pathbase;u64 snap_follows;dout (" adding %p ino %llx.%llx cap %p %lld %s\n" , inode,ceph_vinop (inode), cap, cap->cap_id,ceph_cap_string (cap->issued)); + dentry =d_find_primary (inode); +if (dentry) { +/* set pathbase to parent dir when msg_version >= 2 */ + path =ceph_mdsc_build_path (dentry, &pathlen, &pathbase, + recon_state->msg_version >=2 ); +dput (dentry); +if (IS_ERR (path)) { + err =PTR_ERR (path); + goto out_err; + } + }else { + path =NULL ; + pathlen =0 ; + pathbase =0 ; + } +spin_lock (&ci->i_ceph_lock); cap->seq =0 ;/* reset cap seq */ cap->issue_seq =0 ;/* and issue_seq */
@@ -3652,7 +3704,7 @@ static int reconnect_caps_cb(struct inode *inode, struct ceph_cap *cap, rec.v2.wanted =cpu_to_le32 (__ceph_caps_wanted (ci)); rec.v2.issued =cpu_to_le32 (cap->issued); rec.v2.snaprealm =cpu_to_le64 (ci->i_snap_realm->ino); - rec.v2.pathbase =0 ; + rec.v2.pathbase =cpu_to_le64 (pathbase); rec.v2.flock_len = (__force __le32) ((ci->i_ceph_flags &CEPH_I_ERROR_FILELOCK ) ?0 :1 ); }else {
@@ -3663,7 +3715,7 @@ static int reconnect_caps_cb(struct inode *inode, struct ceph_cap *cap,ceph_encode_timespec64 (&rec.v1.mtime, &inode->i_mtime);ceph_encode_timespec64 (&rec.v1.atime, &inode->i_atime); rec.v1.snaprealm =cpu_to_le64 (ci->i_snap_realm->ino); - rec.v1.pathbase =0 ; + rec.v1.pathbase =cpu_to_le64 (pathbase); }if (list_empty (&ci->i_cap_snaps)) {
@@ -3725,7 +3777,7 @@ encode_again:sizeof (struct ceph_filelock ); rec.v2.flock_len =cpu_to_le32 (struct_len); - struct_len +=sizeof (u32) +sizeof (rec.v2); + struct_len +=sizeof (u32) + pathlen +sizeof (rec.v2);if (struct_v >=2 ) struct_len +=sizeof (u64);/* snap_follows */
@@ -3749,7 +3801,7 @@ encode_again:ceph_pagelist_encode_8 (pagelist,1 );ceph_pagelist_encode_32 (pagelist, struct_len); } -ceph_pagelist_encode_string (pagelist,NULL ,0 ); +ceph_pagelist_encode_string (pagelist, path, pathlen);ceph_pagelist_append (pagelist, &rec,sizeof (rec.v2));ceph_locks_to_pagelist (flocks, pagelist, num_fcntl_locks, num_flock_locks);
@@ -3758,39 +3810,20 @@ encode_again: out_freeflocks:kfree (flocks); }else { -u64 pathbase =0 ; -int pathlen =0 ; -char *path =NULL ; -struct dentry *dentry; - - dentry =d_find_alias (inode); -if (dentry) { - path =ceph_mdsc_build_path (dentry, - &pathlen, &pathbase,0 ); -dput (dentry); -if (IS_ERR (path)) { - err =PTR_ERR (path); - goto out_err; - } - rec.v1.pathbase =cpu_to_le64 (pathbase); - } - err =ceph_pagelist_reserve (pagelist,sizeof (u64) +sizeof (u32) + pathlen +sizeof (rec.v1)); -if (err) { - goto out_freepath; - } +if (err) + goto out_err;ceph_pagelist_encode_64 (pagelist,ceph_ino (inode));ceph_pagelist_encode_string (pagelist, path, pathlen);ceph_pagelist_append (pagelist, &rec,sizeof (rec.v1)); -out_freepath: -ceph_mdsc_free_path (path, pathlen); } out_err: -if (err >=0 ) +ceph_mdsc_free_path (path, pathlen); +if (!err) recon_state->nr_caps++;return err; }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 153/391 drivers: watchdog: rdc321x_wdt: Fix race condition bugs
In reply to Greg Kroah-HartmanFrom: Madhuparna Bhowmik <[email protected]>
[ Upstream commit 4b2e7f99cdd314263c9d172bc17193b8b6bba463 ]
In rdc321x_wdt_probe(), rdc321x_wdt_device.queue is initialized after misc_register(), hence if ioctl is called before its initialization which can call rdc321x_wdt_start() function, it will see an uninitialized value of rdc321x_wdt_device.queue, hence initialize it before misc_register().
Also, rdc321x_wdt_device.default_ticks is accessed in reset() function called from write callback, thus initialize it before misc_register().
Found by Linux Driver Verification project (linuxtesting.org).
--- drivers/watchdog/rdc321x_wdt.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/watchdog/rdc321x_wdt.c +2 -3
@@ -231,6 +231,8 @@ static int rdc321x_wdt_probe(struct platform_device *pdev) rdc321x_wdt_device.sb_pdev = pdata->sb_pdev; rdc321x_wdt_device.base_reg = r->start; + rdc321x_wdt_device.queue =0 ; + rdc321x_wdt_device.default_ticks = ticks; err =misc_register (&rdc321x_wdt_misc);if (err <0 ) {
@@ -245,14 +247,11 @@ static int rdc321x_wdt_probe(struct platform_device *pdev) rdc321x_wdt_device.base_reg, RDC_WDT_RST);init_completion (&rdc321x_wdt_device.stop); - rdc321x_wdt_device.queue =0 ;clear_bit (0 , &rdc321x_wdt_device.inuse);timer_setup (&rdc321x_wdt_device.timer, rdc321x_wdt_trigger,0 ); - rdc321x_wdt_device.default_ticks = ticks; -dev_info (&pdev->dev,"watchdog init success\n" );return 0 ;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 154/391 jbd2: avoid transaction reuse after reformatting
In reply to Greg Kroah-HartmanFrom: changfengnan <[email protected]>
[ Upstream commit fc750a3b44bdccb9fb96d6abbc48a9b8e480ce7b ]
When ext4 is formatted with lazy_journal_init=1 and transactions from the previous filesystem are still on disk, it is possible that they are considered during a recovery after a crash. Because the checksum seed has changed, the CRC check will fail, and the journal recovery fails with checksum error although the journal is otherwise perfectly valid. Fix the problem by checking commit block time stamps to determine whether the data in the journal block is just stale or whether it is indeed corrupt.
--- fs/jbd2/recovery.c | 78 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 12 deletions(-)
fs/jbd2/recovery.c +66 -12
@@ -428,6 +428,8 @@ static int do_one_pass(journal_t *journal,__u32 crc32_sum = ~0 ;/* Transactional Checksums */ int descr_csum_size =0 ;int block_error =0 ; +bool need_check_commit_time = false; +__u64 last_trans_commit_time =0 , commit_time;/* * First thing is to establish what we expect to find in the log
@@ -520,12 +522,21 @@ static int do_one_pass(journal_t *journal,if (descr_csum_size >0 && !jbd2_descriptor_block_csum_verify (journal, bh->b_data)) { -printk (KERN_ERR "JBD2: Invalid checksum " -"recovering block %lu in log\n" , - next_log_block); - err = -EFSBADCRC ; -brelse (bh); - goto failed; +/* +* PASS_SCAN can see stale blocks due to lazy +* journal init. Don't error out on those yet. +*/ +if (pass !=PASS_SCAN ) { +pr_err ("JBD2: Invalid checksum recovering block %lu in log\n" , + next_log_block); + err = -EFSBADCRC ; +brelse (bh); + goto failed; + } + need_check_commit_time = true; +jbd_debug (1 , +"invalid descriptor block found in %lu\n" , + next_log_block); }/* If it is a valid descriptor block, replay it
@@ -535,6 +546,7 @@ static int do_one_pass(journal_t *journal,if (pass !=PASS_REPLAY ) {if (pass ==PASS_SCAN &&jbd2_has_feature_checksum (journal) && + !need_check_commit_time && !info->end_transaction) { if (calc_chksums(journal, bh, &next_log_block,
@@ -683,11 +695,41 @@ static int do_one_pass(journal_t *journal,* mentioned conditions. Hence assume * "Interrupted Commit".) */ + commit_time =be64_to_cpu ( + ((struct commit_header *)bh->b_data)->h_commit_sec); +/* +* If need_check_commit_time is set, it means we are in +* PASS_SCAN and csum verify failed before. If +* commit_time is increasing, it's the same journal, +* otherwise it is stale journal block, just end this +* recovery. +*/ +if (need_check_commit_time) { +if (commit_time >= last_trans_commit_time) { +pr_err ("JBD2: Invalid checksum found in transaction %u\n" , + next_commit_ID); + err = -EFSBADCRC ; +brelse (bh); + goto failed; + } + ignore_crc_mismatch: +/* +* It likely does not belong to same journal, +* just end this recovery with success. +*/ +jbd_debug (1 ,"JBD2: Invalid checksum ignored in transaction %u, likely stale data\n" , + next_commit_ID); + err =0 ; +brelse (bh); + goto done; + } -/* Found an expected commit block: if checksums -* are present verify them in PASS_SCAN; else not +/* +* Found an expected commit block: if checksums +* are present, verify them in PASS_SCAN; else not * much to do other than move on to the next sequence -* number. */ +* number. +*/ if (pass ==PASS_SCAN &&jbd2_has_feature_checksum (journal)) { struct commit_header *cbh =
@@ -719,6 +761,8 @@ static int do_one_pass(journal_t *journal, !jbd2_commit_block_csum_verify(journal, bh->b_data)) { chksum_error: +if (commit_time < last_trans_commit_time) + goto ignore_crc_mismatch; info->end_transaction = next_commit_ID;if (!jbd2_has_feature_async_commit (journal)) {
@@ -728,11 +772,24 @@ static int do_one_pass(journal_t *journal,break ; } } +if (pass ==PASS_SCAN ) + last_trans_commit_time = commit_time;brelse (bh); next_commit_ID++;continue ;case JBD2_REVOKE_BLOCK : +/* +* Check revoke block crc in pass_scan, if csum verify +* failed, check commit block time later. +*/ +if (pass ==PASS_SCAN && + !jbd2_descriptor_block_csum_verify (journal, + bh->b_data)) { +jbd_debug (1 ,"JBD2: invalid revoke block found in %lu\n" , + next_log_block); + need_check_commit_time = true; + }/* If we aren't in the REVOKE pass, then we can * just skip over this block. */ if (pass !=PASS_REVOKE ) {
@@ -800,9 +857,6 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh, offset =sizeof (jbd2_journal_revoke_header_t); rcount =be32_to_cpu (header->r_count); -if (!jbd2_descriptor_block_csum_verify (journal, header)) -return -EFSBADCRC ; -if (jbd2_journal_has_csum_v2or3 (journal)) csum_size =sizeof (struct jbd2_journal_block_tail );if (rcount > journal->j_blocksize - csum_size)
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 155/391 ext4: Detect already used quota file early
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
[ Upstream commit e0770e91424f694b461141cbc99adf6b23006b60 ]
When we try to use file already used as a quota file again (for the same or different quota type), strange things can happen. At the very least lockdep annotations may be wrong but also inode flags may be wrongly set / reset. When the file is used for two quota types at once we can even corrupt the file and likely crash the kernel. Catch all these cases by checking whether passed file is already used as quota file and bail early in that case.
This fixes occasional generic/219 failure due to lockdep complaint.
--- fs/ext4/super.c | 5 +++++ 1 file changed, 5 insertions(+)
fs/ext4/super.c +5 -0
@@ -6042,6 +6042,11 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,/* Quotafile not on the same filesystem? */ if (path->dentry->d_sb != sb)return -EXDEV ; + +/* Quota already enabled for this file? */ +if (IS_NOQUOTA (d_inode (path->dentry))) +return -EBUSY ; +/* Journaling quota? */ if (EXT4_SB (sb)->s_qf_names[type]) {/* Quotafile not in fs root? */
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 156/391 KVM: PPC: Book3S HV: Do not allocate HPT for a nested guest
In reply to Greg Kroah-HartmanFrom: Fabiano Rosas <[email protected]>
[ Upstream commit 05e6295dc7de859c9d56334805485c4d20bebf25 ]
The current nested KVM code does not support HPT guests. This is informed/enforced in some ways:
- Hosts < P9 will not be able to enable the nested HV feature;
- The nested hypervisor MMU capabilities will not contain KVM_CAP_PPC_MMU_HASH_V3;
- QEMU reflects the MMU capabilities in the 'ibm,arch-vec-5-platform-support' device-tree property;
- The nested guest, at 'prom_parse_mmu_model' ignores the 'disable_radix' kernel command line option if HPT is not supported;
- The KVM_PPC_CONFIGURE_V3_MMU ioctl will fail if trying to use HPT.
There is, however, still a way to start a HPT guest by using max-compat-cpu=power8 at the QEMU machine options. This leads to the guest being set to use hash after QEMU calls the KVM_PPC_ALLOCATE_HTAB ioctl.
With the guest set to hash, the nested hypervisor goes through the entry path that has no knowledge of nesting (kvmppc_run_vcpu) and crashes when it tries to execute an hypervisor-privileged (mtspr HDEC) instruction at __kvmppc_vcore_entry:
root@L1:~ $ qemu-system-ppc64 -machine pseries,max-cpu-compat=power8 ...
<snip>
[ 538.543303] CPU: 83 PID: 25185 Comm: CPU 0/KVM Not tainted 5.9.0-rc4 #1
[ 538.543355] NIP: c00800000753f388 LR: c00800000753f368 CTR: c0000000001e5ec0
[ 538.543417] REGS: c0000013e91e33b0 TRAP: 0700 Not tainted (5.9.0-rc4)
[ 538.543470] MSR: 8000000002843033 <SF,VEC,VSX,FP,ME,IR,DR,RI,LE> CR: 22422882 XER: 20040000
[ 538.543546] CFAR: c00800000753f4b0 IRQMASK: 3
GPR00: c0080000075397a0 c0000013e91e3640 c00800000755e600 0000000080000000
GPR04: 0000000000000000 c0000013eab19800 c000001394de0000 00000043a054db72
GPR08: 00000000003b1652 0000000000000000 0000000000000000 c0080000075502e0
GPR12: c0000000001e5ec0 c0000007ffa74200 c0000013eab19800 0000000000000008
GPR16: 0000000000000000 c00000139676c6c0 c000000001d23948 c0000013e91e38b8
GPR20: 0000000000000053 0000000000000000 0000000000000001 0000000000000000
GPR24: 0000000000000001 0000000000000001 0000000000000000 0000000000000001
GPR28: 0000000000000001 0000000000000053 c0000013eab19800 0000000000000001
[ 538.544067] NIP [c00800000753f388] __kvmppc_vcore_entry+0x90/0x104 [kvm_hv]
[ 538.544121] LR [c00800000753f368] __kvmppc_vcore_entry+0x70/0x104 [kvm_hv]
[ 538.544173] Call Trace:
[ 538.544196] [c0000013e91e3640] [c0000013e91e3680] 0xc0000013e91e3680 (unreliable)
[ 538.544260] [c0000013e91e3820] [c0080000075397a0] kvmppc_run_core+0xbc8/0x19d0 [kvm_hv]
[ 538.544325] [c0000013e91e39e0] [c00800000753d99c] kvmppc_vcpu_run_hv+0x404/0xc00 [kvm_hv]
[ 538.544394] [c0000013e91e3ad0] [c0080000072da4fc] kvmppc_vcpu_run+0x34/0x48 [kvm]
[ 538.544472] [c0000013e91e3af0] [c0080000072d61b8] kvm_arch_vcpu_ioctl_run+0x310/0x420 [kvm]
[ 538.544539] [c0000013e91e3b80] [c0080000072c7450] kvm_vcpu_ioctl+0x298/0x778 [kvm]
[ 538.544605] [c0000013e91e3ce0] [c0000000004b8c2c] sys_ioctl+0x1dc/0xc90
[ 538.544662] [c0000013e91e3dc0] [c00000000002f9a4] system_call_exception+0xe4/0x1c0
[ 538.544726] [c0000013e91e3e20] [c00000000000d140] system_call_common+0xf0/0x27c
[ 538.544787] Instruction dump:
[ 538.544821] f86d1098 60000000 60000000 48000099 e8ad0fe8 e8c500a0 e9264140 75290002
[ 538.544886] 7d1602a6 7cec42a6 40820008 7d0807b4 <7d164ba6> 7d083a14 f90d10a0 480104fd
[ 538.544953] ---[ end trace 74423e2b948c2e0c ]---This patch makes the KVM_PPC_ALLOCATE_HTAB ioctl fail when running in the nested hypervisor, causing QEMU to abort.
--- arch/powerpc/kvm/book3s_hv.c | 6 ++++++ 1 file changed, 6 insertions(+)
arch/powerpc/kvm/book3s_hv.c +6 -0
@@ -5257,6 +5257,12 @@ static long kvm_arch_vm_ioctl_hv(struct file *filp,case KVM_PPC_ALLOCATE_HTAB : {u32 htab_order; +/* If we're a nested hypervisor, we currently only support radix */ +if (kvmhv_on_pseries ()) { + r = -EOPNOTSUPP ; +break ; + } + r = -EFAULT ;if (get_user (htab_order, (u32 __user *)argp))break ;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 157/391 scsi: core: Clean up allocation and freeing of sgtables
In reply to Greg Kroah-HartmanFrom: Christoph Hellwig <[email protected]>
[ Upstream commit 7007e9dd56767a95de0947b3f7599bcc2f21687f ]
Rename scsi_init_io() to scsi_alloc_sgtables(), and ensure callers call scsi_free_sgtables() to cleanup failures close to scsi_init_io() instead of leaking it down the generic I/O submission path.
--- drivers/scsi/scsi_lib.c | 22 ++++++++-------------- drivers/scsi/sd.c | 27 +++++++++++++++------------ drivers/scsi/sr.c | 16 ++++++---------- include/scsi/scsi_cmnd.h | 3 ++- 4 files changed, 31 insertions(+), 37 deletions(-)
drivers/scsi/scsi_lib.c +8 -14
@@ -530,7 +530,7 @@ static void scsi_uninit_cmd(struct scsi_cmnd *cmd) } } -static void scsi_free_sgtables (struct scsi_cmnd *cmd) +void scsi_free_sgtables (struct scsi_cmnd *cmd) {if (cmd->sdb.table.nents) sg_free_table_chained(&cmd->sdb.table,
@@ -539,6 +539,7 @@ static void scsi_free_sgtables(struct scsi_cmnd *cmd)sg_free_table_chained (&cmd->prot_sdb->table,SCSI_INLINE_PROT_SG_CNT ); } +EXPORT_SYMBOL_GPL (scsi_free_sgtables);static void scsi_mq_uninit_cmd (struct scsi_cmnd *cmd) {
@@ -966,7 +967,7 @@ static inline bool scsi_cmd_needs_dma_drain(struct scsi_device *sdev, }/** -* scsi_init_io - SCSI I/O initialization function. +* scsi_alloc_sgtables - allocate S/G tables for a command * @cmd: command descriptor we wish to initialize * * Returns:
@@ -974,7 +975,7 @@ static inline bool scsi_cmd_needs_dma_drain(struct scsi_device *sdev,* * BLK_STS_RESOURCE - if the failure is retryable * * BLK_STS_IOERR - if the failure is fatal */ -blk_status_t scsi_init_io (struct scsi_cmnd *cmd) +blk_status_t scsi_alloc_sgtables (struct scsi_cmnd *cmd) {struct scsi_device *sdev = cmd->device;struct request *rq = cmd->request;
@@ -1066,7 +1067,7 @@ out_free_sgtables:scsi_free_sgtables (cmd);return ret; } -EXPORT_SYMBOL (scsi_init_io); +EXPORT_SYMBOL (scsi_alloc_sgtables);/** * scsi_initialize_rq - initialize struct scsi_cmnd partially
@@ -1154,7 +1155,7 @@ static blk_status_t scsi_setup_scsi_cmnd(struct scsi_device *sdev,* submit a request without an attached bio. */ if (req->bio) { -blk_status_t ret =scsi_init_io (cmd); +blk_status_t ret =scsi_alloc_sgtables (cmd);if (unlikely (ret !=BLK_STS_OK ))return ret; }else {
@@ -1194,7 +1195,6 @@ static blk_status_t scsi_setup_cmnd(struct scsi_device *sdev, struct request *req) {struct scsi_cmnd *cmd =blk_mq_rq_to_pdu (req); -blk_status_t ret;if (!blk_rq_bytes (req)) cmd->sc_data_direction =DMA_NONE ;
@@ -1204,14 +1204,8 @@ static blk_status_t scsi_setup_cmnd(struct scsi_device *sdev, cmd->sc_data_direction =DMA_FROM_DEVICE ;if (blk_rq_is_scsi (req)) - ret =scsi_setup_scsi_cmnd (sdev, req); -else - ret =scsi_setup_fs_cmnd (sdev, req); - -if (ret !=BLK_STS_OK ) -scsi_free_sgtables (cmd); - -return ret; +return scsi_setup_scsi_cmnd (sdev, req); +return scsi_setup_fs_cmnd (sdev, req); } static blk_status_t
drivers/scsi/sd.c +15 -12
@@ -866,7 +866,7 @@ static blk_status_t sd_setup_unmap_cmnd(struct scsi_cmnd *cmd) cmd->transfersize = data_len; rq->timeout =SD_TIMEOUT ; -return scsi_init_io (cmd); +return scsi_alloc_sgtables (cmd); } static blk_status_t sd_setup_write_same16_cmnd(struct scsi_cmnd *cmd,
@@ -897,7 +897,7 @@ static blk_status_t sd_setup_write_same16_cmnd(struct scsi_cmnd *cmd, cmd->transfersize = data_len; rq->timeout = unmap ?SD_TIMEOUT :SD_WRITE_SAME_TIMEOUT ; -return scsi_init_io (cmd); +return scsi_alloc_sgtables (cmd); } static blk_status_t sd_setup_write_same10_cmnd(struct scsi_cmnd *cmd,
@@ -928,7 +928,7 @@ static blk_status_t sd_setup_write_same10_cmnd(struct scsi_cmnd *cmd, cmd->transfersize = data_len; rq->timeout = unmap ?SD_TIMEOUT :SD_WRITE_SAME_TIMEOUT ; -return scsi_init_io (cmd); +return scsi_alloc_sgtables (cmd); }static blk_status_t sd_setup_write_zeroes_cmnd (struct scsi_cmnd *cmd)
@@ -1069,7 +1069,7 @@ static blk_status_t sd_setup_write_same_cmnd(struct scsi_cmnd *cmd)* knows how much to actually write. */ rq->__data_len = sdp->sector_size; - ret =scsi_init_io (cmd); + ret =scsi_alloc_sgtables (cmd); rq->__data_len =blk_rq_bytes (rq);return ret;
@@ -1187,23 +1187,24 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd)unsigned int dif;bool dix; - ret =scsi_init_io (cmd); + ret =scsi_alloc_sgtables (cmd);if (ret !=BLK_STS_OK )return ret; + ret =BLK_STS_IOERR ;if (!scsi_device_online (sdp) || sdp->changed) {scmd_printk (KERN_ERR , cmd,"device offline or changed\n" ); -return BLK_STS_IOERR ; + goto fail; }if (blk_rq_pos (rq) +blk_rq_sectors (rq) >get_capacity (rq->rq_disk)) {scmd_printk (KERN_ERR , cmd,"access beyond end of device\n" ); -return BLK_STS_IOERR ; + goto fail; }if ((blk_rq_pos (rq) & mask) || (blk_rq_sectors (rq) & mask)) {scmd_printk (KERN_ERR , cmd,"request not aligned to the logical block size\n" ); -return BLK_STS_IOERR ; + goto fail; }/*
@@ -1225,7 +1226,7 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd)if (req_op (rq) ==REQ_OP_ZONE_APPEND ) { ret =sd_zbc_prepare_zone_append (cmd, &lba, nr_blocks);if (ret) -return ret; + goto fail; } fua = rq->cmd_flags &REQ_FUA ?0x8 :0 ;
@@ -1253,7 +1254,7 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd) }if (unlikely (ret !=BLK_STS_OK )) -return ret; + goto fail;/* * We shouldn't disconnect in the middle of a sector, so with a dumb
@@ -1277,10 +1278,12 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd) blk_rq_sectors(rq)));/* -* This indicates that the command is ready from our end to be -* queued. +* This indicates that the command is ready from our end to be queued. */ return BLK_STS_OK ; +fail: +scsi_free_sgtables (cmd); +return ret; }static blk_status_t sd_init_command (struct scsi_cmnd *cmd)
drivers/scsi/sr.c +6 -10
@@ -392,15 +392,11 @@ static blk_status_t sr_init_command(struct scsi_cmnd *SCpnt)struct request *rq = SCpnt->request;blk_status_t ret; - ret =scsi_init_io (SCpnt); + ret =scsi_alloc_sgtables (SCpnt);if (ret !=BLK_STS_OK ) - goto out; +return ret; cd =scsi_cd (rq->rq_disk); -/* from here on until we're complete, any goto out -* is used for a killable error condition */ - ret =BLK_STS_IOERR ; -SCSI_LOG_HLQUEUE (1 ,scmd_printk (KERN_INFO , SCpnt,"Doing sr request, block = %d\n" , block));
@@ -509,12 +505,12 @@ static blk_status_t sr_init_command(struct scsi_cmnd *SCpnt) SCpnt->allowed =MAX_RETRIES ;/* -* This indicates that the command is ready from our end to be -* queued. +* This indicates that the command is ready from our end to be queued. */ - ret =BLK_STS_OK ; +return BLK_STS_OK ; out: -return ret; +scsi_free_sgtables (SCpnt); +return BLK_STS_IOERR ; }static int sr_block_open (struct block_device *bdev,fmode_t mode)
include/scsi/scsi_cmnd.h +2 -1
@@ -165,7 +165,8 @@ extern void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count, size_t *offset, size_t *len);extern void scsi_kunmap_atomic_sg (void *virt); -extern blk_status_t scsi_init_io (struct scsi_cmnd *cmd); +blk_status_t scsi_alloc_sgtables (struct scsi_cmnd *cmd); +void scsi_free_sgtables (struct scsi_cmnd *cmd);#ifdef CONFIG_SCSI_DMA extern int scsi_dma_map (struct scsi_cmnd *cmd);
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 158/391 gfs2: call truncate_inode_pages_final for address space glocks
In reply to Greg Kroah-HartmanFrom: Bob Peterson <[email protected]>
[ Upstream commit ee1e2c773e4f4ce2213f9d77cc703b669ca6fa3f ]
Before this patch, we were not calling truncate_inode_pages_final for the address space for glocks, which left the possibility of a leak. We now take care of the problem instead of complaining, and we do it during glock tear-down..
--- fs/gfs2/glock.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
fs/gfs2/glock.c +6 -1
@@ -270,7 +270,12 @@ static void __gfs2_glock_put(struct gfs2_glock *gl)gfs2_glock_remove_from_lru (gl);spin_unlock (&gl->gl_lockref.lock);GLOCK_BUG_ON (gl, !list_empty (&gl->gl_holders)); -GLOCK_BUG_ON (gl, mapping && mapping->nrpages && !gfs2_withdrawn (sdp)); +if (mapping) { +truncate_inode_pages_final (mapping); +if (!gfs2_withdrawn (sdp)) +GLOCK_BUG_ON (gl, mapping->nrpages || + mapping->nrexceptional); + }trace_gfs2_glock_put (gl); sdp->sd_lockstruct.ls_ops->lm_put_lock (gl); }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 159/391 gfs2: Fix NULL pointer dereference in gfs2_rgrp_dump
In reply to Greg Kroah-HartmanFrom: Andrew Price <[email protected]>
[ Upstream commit 0e539ca1bbbe85a86549c97a30a765ada4a09df9 ]
When an rindex entry is found to be corrupt, compute_bitstructs() calls gfs2_consist_rgrpd() which calls gfs2_rgrp_dump() like this:
gfs2_rgrp_dump(NULL, rgd->rd_gl, fs_id_buf);
gfs2_rgrp_dump then dereferences the gl without checking it and we get
BUG: KASAN: null-ptr-deref in gfs2_rgrp_dump+0x28/0x280
because there's no rgrp glock involved while reading the rindex on mount.
Fix this by changing gfs2_rgrp_dump to take an rgrp argument.
--- fs/gfs2/glops.c | 11 ++++++++++- fs/gfs2/rgrp.c | 9 +++------ fs/gfs2/rgrp.h | 2 +- fs/gfs2/util.c | 2 +- 4 files changed, 15 insertions(+), 9 deletions(-)
fs/gfs2/glops.c +10 -1
@@ -227,6 +227,15 @@ static void rgrp_go_inval(struct gfs2_glock *gl, int flags) rgd->rd_flags &= ~GFS2_RDF_UPTODATE ; } +static void gfs2_rgrp_go_dump (struct seq_file *seq,struct gfs2_glock *gl, +const char *fs_id_buf) +{ +struct gfs2_rgrpd *rgd =gfs2_glock2rgrp (gl); + +if (rgd) +gfs2_rgrp_dump (seq, rgd, fs_id_buf); +} +static struct gfs2_inode *gfs2_glock2inode (struct gfs2_glock *gl) {struct gfs2_inode *ip;
@@ -712,7 +721,7 @@ const struct gfs2_glock_operations gfs2_rgrp_glops = { .go_sync = rgrp_go_sync, .go_inval = rgrp_go_inval, .go_lock = gfs2_rgrp_go_lock, - .go_dump = gfs2_rgrp_dump, + .go_dump = gfs2_rgrp_go_dump, .go_type = LM_TYPE_RGRP, .go_flags = GLOF_LVB, };
fs/gfs2/rgrp.c +3 -6
@@ -2209,20 +2209,17 @@ static void rgblk_free(struct gfs2_sbd *sdp, struct gfs2_rgrpd *rgd,/** * gfs2_rgrp_dump - print out an rgrp * @seq: The iterator -* @gl: The glock in question +* @rgd: The rgrp in question * @fs_id_buf: pointer to file system id (if requested) * */ -void gfs2_rgrp_dump (struct seq_file *seq,struct gfs2_glock *gl, +void gfs2_rgrp_dump (struct seq_file *seq,struct gfs2_rgrpd *rgd,const char *fs_id_buf) { -struct gfs2_rgrpd *rgd = gl->gl_object;struct gfs2_blkreserv *trs;const struct rb_node *n; -if (rgd ==NULL ) -return ; gfs2_print_dbg(seq, "%s R: n:%llu f:%02x b:%u/%u i:%u r:%u e:%u\n", fs_id_buf, (unsigned long long)rgd->rd_addr, rgd->rd_flags,
@@ -2253,7 +2250,7 @@ static void gfs2_rgrp_error(struct gfs2_rgrpd *rgd) (unsigned long long)rgd->rd_addr);fs_warn (sdp,"umount on all nodes and run fsck.gfs2 to fix the error\n" );sprintf (fs_id_buf,"fsid=%s: " , sdp->sd_fsname); -gfs2_rgrp_dump (NULL , rgd->rd_gl, fs_id_buf); +gfs2_rgrp_dump (NULL , rgd, fs_id_buf); rgd->rd_flags |=GFS2_RDF_ERROR ; }
fs/gfs2/rgrp.h +1 -1
@@ -67,7 +67,7 @@ extern void gfs2_rlist_add(struct gfs2_inode *ip, struct gfs2_rgrp_list *rlist,extern void gfs2_rlist_alloc (struct gfs2_rgrp_list *rlist);extern void gfs2_rlist_free (struct gfs2_rgrp_list *rlist);extern u64 gfs2_ri_total (struct gfs2_sbd *sdp); -extern void gfs2_rgrp_dump (struct seq_file *seq,struct gfs2_glock *gl, +extern void gfs2_rgrp_dump (struct seq_file *seq,struct gfs2_rgrpd *rgd,const char *fs_id_buf); extern int gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset, struct buffer_head *bh,
fs/gfs2/util.c +1 -1
@@ -419,7 +419,7 @@ void gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd,char fs_id_buf[sizeof (sdp->sd_fsname) +7 ];sprintf (fs_id_buf,"fsid=%s: " , sdp->sd_fsname); -gfs2_rgrp_dump (NULL , rgd->rd_gl, fs_id_buf); +gfs2_rgrp_dump (NULL , rgd, fs_id_buf);gfs2_lm (sdp,"fatal: filesystem consistency error\n" " RG = %llu\n"
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 160/391 gfs2: use-after-free in sysfs deregistration
In reply to Greg Kroah-HartmanFrom: Jamie Iles <[email protected]>
[ Upstream commit c2a04b02c060c4858762edce4674d5cba3e5a96f ]
syzkaller found the following splat with CONFIG_DEBUG_KOBJECT_RELEASE=y:
Read of size 1 at addr ffff000028e896b8 by task kworker/1:2/228 CPU: 1 PID: 228 Comm: kworker/1:2 Tainted: G S 5.9.0-rc8+ #101 Hardware name: linux,dummy-virt (DT) Workqueue: events kobject_delayed_cleanup Call trace: dump_backtrace+0x0/0x4d8 show_stack+0x34/0x48 dump_stack+0x174/0x1f8 print_address_description.constprop.0+0x5c/0x550 kasan_report+0x13c/0x1c0 __asan_report_load1_noabort+0x34/0x60 memcmp+0xd0/0xd8 gfs2_uevent+0xc4/0x188 kobject_uevent_env+0x54c/0x1240 kobject_uevent+0x2c/0x40 __kobject_del+0x190/0x1d8 kobject_delayed_cleanup+0x2bc/0x3b8 process_one_work+0x96c/0x18c0 worker_thread+0x3f0/0xc30 kthread+0x390/0x498 ret_from_fork+0x10/0x18 Allocated by task 1110: kasan_save_stack+0x28/0x58 __kasan_kmalloc.isra.0+0xc8/0xe8 kasan_kmalloc+0x10/0x20 kmem_cache_alloc_trace+0x1d8/0x2f0 alloc_super+0x64/0x8c0 sget_fc+0x110/0x620 get_tree_bdev+0x190/0x648 gfs2_get_tree+0x50/0x228 vfs_get_tree+0x84/0x2e8 path_mount+0x1134/0x1da8 do_mount+0x124/0x138 __arm64_sys_mount+0x164/0x238 el0_svc_common.constprop.0+0x15c/0x598 do_el0_svc+0x60/0x150 el0_svc+0x34/0xb0 el0_sync_handler+0xc8/0x5b4 el0_sync+0x15c/0x180 Freed by task 228: kasan_save_stack+0x28/0x58 kasan_set_track+0x28/0x40 kasan_set_free_info+0x24/0x48 __kasan_slab_free+0x118/0x190 kasan_slab_free+0x14/0x20 slab_free_freelist_hook+0x6c/0x210 kfree+0x13c/0x460
Use the same pattern as f2fs + ext4 where the kobject destruction must complete before allowing the FS itself to be freed. This means that we need an explicit free_sbd in the callers.
--- fs/gfs2/incore.h | 1 + fs/gfs2/ops_fstype.c | 22 +++++----------------- fs/gfs2/super.c | 1 + fs/gfs2/sys.c | 5 ++++- 4 files changed, 11 insertions(+), 18 deletions(-)
fs/gfs2/incore.h +1 -0
@@ -705,6 +705,7 @@ struct gfs2_sbd {struct super_block *sd_vfs;struct gfs2_pcpu_lkstats __percpu *sd_lkstats;struct kobject sd_kobj; +struct completion sd_kobj_unregister;unsigned long sd_flags;/* SDF_... */ struct gfs2_sb_host sd_sb;
fs/gfs2/ops_fstype.c +5 -17
@@ -1062,26 +1062,14 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) } error =init_names (sdp, silent); -if (error) { -/* In this case, we haven't initialized sysfs, so we have to -manually free the sdp. */ -free_sbd (sdp); - sb->s_fs_info =NULL ; -return error; - } +if (error) + goto fail_free;snprintf (sdp->sd_fsname,sizeof (sdp->sd_fsname),"%s" , sdp->sd_table_name); error =gfs2_sys_fs_add (sdp); -/* -* If we hit an error here, gfs2_sys_fs_add will have called function -* kobject_put which causes the sysfs usage count to go to zero, which -* causes sysfs to call function gfs2_sbd_release, which frees sdp. -* Subsequent error paths here will call gfs2_sys_fs_del, which also -* kobject_put to free sdp. -*/ if (error) -return error; + goto fail_free;gfs2_create_debugfs_file (sdp);
@@ -1179,9 +1167,9 @@ fail_lm:gfs2_lm_unmount (sdp); fail_debug:gfs2_delete_debugfs_file (sdp); -/* gfs2_sys_fs_del must be the last thing we do, since it causes -* sysfs to call function gfs2_sbd_release, which frees sdp. */ gfs2_sys_fs_del (sdp); +fail_free: +free_sbd (sdp); sb->s_fs_info =NULL ;return error; }
fs/gfs2/super.c +1 -0
@@ -736,6 +736,7 @@ restart:/* At this point, we're through participating in the lockspace */ gfs2_sys_fs_del (sdp); +free_sbd (sdp); }/**
fs/gfs2/sys.c +4 -1
@@ -303,7 +303,7 @@ static void gfs2_sbd_release(struct kobject *kobj) { struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj); -free_sbd (sdp); +complete (&sdp->sd_kobj_unregister); }static struct kobj_type gfs2_ktype = {
@@ -655,6 +655,7 @@ int gfs2_sys_fs_add(struct gfs2_sbd *sdp)sprintf (ro,"RDONLY=%d" ,sb_rdonly (sb));sprintf (spectator,"SPECTATOR=%d" , sdp->sd_args.ar_spectator ?1 :0 ); +init_completion (&sdp->sd_kobj_unregister); sdp->sd_kobj.kset = gfs2_kset; error =kobject_init_and_add (&sdp->sd_kobj, &gfs2_ktype,NULL ,"%s" , sdp->sd_table_name);
@@ -685,6 +686,7 @@ fail_tune: fail_reg:fs_err (sdp,"error %d adding sysfs files\n" , error);kobject_put (&sdp->sd_kobj); +wait_for_completion (&sdp->sd_kobj_unregister); sb->s_fs_info =NULL ;return error; }
@@ -695,6 +697,7 @@ void gfs2_sys_fs_del(struct gfs2_sbd *sdp)sysfs_remove_group (&sdp->sd_kobj, &tune_group);sysfs_remove_group (&sdp->sd_kobj, &lock_module_group);kobject_put (&sdp->sd_kobj); +wait_for_completion (&sdp->sd_kobj_unregister); } static int gfs2_uevent(struct kset *kset, struct kobject *kobj,
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 161/391 gfs2: add validation checks for size of superblock
In reply to Greg Kroah-HartmanFrom: Anant Thazhemadam <[email protected]>
[ Upstream commit 0ddc5154b24c96f20e94d653b0a814438de6032b ]
In gfs2_check_sb(), no validation checks are performed with regards to the size of the superblock.
syzkaller detected a slab-out-of-bounds bug that was primarily caused because the block size for a superblock was set to zero.
A valid size for a superblock is a power of 2 between 512 and PAGE_SIZE. Performing validation checks and ensuring that the size of the superblock is valid fixes this bug.
--- fs/gfs2/ops_fstype.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)
fs/gfs2/ops_fstype.c +11 -7
@@ -169,15 +169,19 @@ static int gfs2_check_sb(struct gfs2_sbd *sdp, int silent)return -EINVAL ; } -/* If format numbers match exactly, we're done. */ - -if (sb->sb_fs_format ==GFS2_FORMAT_FS && - sb->sb_multihost_format ==GFS2_FORMAT_MULTI ) -return 0 ; +if (sb->sb_fs_format !=GFS2_FORMAT_FS || + sb->sb_multihost_format !=GFS2_FORMAT_MULTI ) { +fs_warn (sdp,"Unknown on-disk format, unable to mount\n" ); +return -EINVAL ; + } -fs_warn (sdp,"Unknown on-disk format, unable to mount\n" ); +if (sb->sb_bsize <512 || sb->sb_bsize >PAGE_SIZE || + (sb->sb_bsize & (sb->sb_bsize -1 ))) { +pr_warn ("Invalid superblock size\n" ); +return -EINVAL ; + } -return -EINVAL ; +return 0 ; }static void end_bio_io_page (struct bio *bio)
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 162/391 Handle STATUS_IO_TIMEOUT gracefully
In reply to Greg Kroah-HartmanFrom: Rohith Surabattula <[email protected]>
[ Upstream commit 8e670f77c4a55013db6d23b962f9bf6673a5e7b6 ]
Currently STATUS_IO_TIMEOUT is not treated as retriable error. It is currently mapped to ETIMEDOUT and returned to userspace for most system calls. STATUS_IO_TIMEOUT is returned by server in case of unavailability or throttling errors.
This patch will map the STATUS_IO_TIMEOUT to EAGAIN, so that it can be retried. Also, added a check to drop the connection to not overload the server in case of ongoing unavailability.
--- fs/cifs/cifsglob.h | 2 ++ fs/cifs/connect.c | 15 ++++++++++++++- fs/cifs/smb2maperror.c | 2 +- fs/cifs/smb2ops.c | 15 +++++++++++++++ 4 files changed, 32 insertions(+), 2 deletions(-)
fs/cifs/cifsglob.h +2 -0
@@ -510,6 +510,8 @@ struct smb_version_operations { struct fiemap_extent_info *, u64, u64);/* version specific llseek implementation */ loff_t (*llseek)(struct file *,struct cifs_tcon *,loff_t ,int ); +/* Check for STATUS_IO_TIMEOUT */ +bool (*is_status_io_timeout)(char *buf); };struct smb_version_values {
fs/cifs/connect.c +14 -1
@@ -69,6 +69,9 @@ extern bool disable_legacy_dialects;#define TLINK_ERROR_EXPIRE (1 * HZ)#define TLINK_IDLE_EXPIRE (600 * HZ) +/* Drop the connection to not overload the server */ +#define NUM_STATUS_IO_TIMEOUT 5 +enum {/* Mount options that take no arguments */ Opt_user_xattr, Opt_nouser_xattr,
@@ -1117,7 +1120,7 @@ cifs_demultiplex_thread(void *p)struct task_struct *task_to_wake =NULL ;struct mid_q_entry *mids[MAX_COMPOUND ];char *bufs[MAX_COMPOUND ]; -unsigned int noreclaim_flag; +unsigned int noreclaim_flag, num_io_timeout =0 ; noreclaim_flag =memalloc_noreclaim_save ();cifs_dbg (FYI ,"Demultiplex PID: %d\n" ,task_pid_nr (current));
@@ -1213,6 +1216,16 @@ next_pdu:continue ; } +if (server->ops->is_status_io_timeout && + server->ops->is_status_io_timeout (buf)) { + num_io_timeout++; +if (num_io_timeout >NUM_STATUS_IO_TIMEOUT ) { +cifs_reconnect (server); + num_io_timeout =0 ; +continue ; + } + } + server->lstrp = jiffies;for (i =0 ; i < num_mids; i++) {
fs/cifs/smb2maperror.c +1 -1
@@ -488,7 +488,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = { {STATUS_PIPE_CONNECTED, -EIO, "STATUS_PIPE_CONNECTED"}, {STATUS_PIPE_LISTENING, -EIO, "STATUS_PIPE_LISTENING"}, {STATUS_INVALID_READ_MODE, -EIO, "STATUS_INVALID_READ_MODE"}, - {STATUS_IO_TIMEOUT, -ETIMEDOUT, "STATUS_IO_TIMEOUT"}, + {STATUS_IO_TIMEOUT, -EAGAIN, "STATUS_IO_TIMEOUT"}, {STATUS_FILE_FORCED_CLOSED, -EIO, "STATUS_FILE_FORCED_CLOSED"}, {STATUS_PROFILING_NOT_STARTED, -EIO, "STATUS_PROFILING_NOT_STARTED"}, {STATUS_PROFILING_NOT_STOPPED, -EIO, "STATUS_PROFILING_NOT_STOPPED"},
fs/cifs/smb2ops.c +15 -0
@@ -2346,6 +2346,17 @@ smb2_is_session_expired(char *buf)return true; } +static bool +smb2_is_status_io_timeout (char *buf) +{ +struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; + +if (shdr->Status ==STATUS_IO_TIMEOUT ) +return true; +else +return false; +} +static int smb2_oplock_response (struct cifs_tcon *tcon,struct cifs_fid *fid,struct cifsInodeInfo *cinode)
@@ -4816,6 +4827,7 @@ struct smb_version_operations smb20_operations = { .make_node = smb2_make_node, .fiemap = smb3_fiemap, .llseek = smb3_llseek, + .is_status_io_timeout = smb2_is_status_io_timeout, };struct smb_version_operations smb21_operations = {
@@ -4916,6 +4928,7 @@ struct smb_version_operations smb21_operations = { .make_node = smb2_make_node, .fiemap = smb3_fiemap, .llseek = smb3_llseek, + .is_status_io_timeout = smb2_is_status_io_timeout, };struct smb_version_operations smb30_operations = {
@@ -5026,6 +5039,7 @@ struct smb_version_operations smb30_operations = { .make_node = smb2_make_node, .fiemap = smb3_fiemap, .llseek = smb3_llseek, + .is_status_io_timeout = smb2_is_status_io_timeout, };struct smb_version_operations smb311_operations = {
@@ -5137,6 +5151,7 @@ struct smb_version_operations smb311_operations = { .make_node = smb2_make_node, .fiemap = smb3_fiemap, .llseek = smb3_llseek, + .is_status_io_timeout = smb2_is_status_io_timeout, };struct smb_version_values smb20_values = {
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 163/391 cifs: handle -EINTR in cifs_setattr
In reply to Greg Kroah-HartmanFrom: Ronnie Sahlberg <[email protected]>
[ Upstream commit c6cc4c5a72505a0ecefc9b413f16bec512f38078 ]
RHBZ: 1848178
Some calls that set attributes, like utimensat(), are not supposed to return -EINTR and thus do not have handlers for this in glibc which causes us to leak -EINTR to the applications which are also unprepared to handle it.
For example tar will break if utimensat() return -EINTR and abort unpacking the archive. Other applications may break too.
To handle this we add checks, and retry, for -EINTR in cifs_setattr()
--- fs/cifs/inode.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
fs/cifs/inode.c +9 -4
@@ -2883,13 +2883,18 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs) {struct cifs_sb_info *cifs_sb =CIFS_SB (direntry->d_sb);struct cifs_tcon *pTcon =cifs_sb_master_tcon (cifs_sb); +int rc, retries =0 ; -if (pTcon->unix_ext) -return cifs_setattr_unix (direntry, attrs); - -return cifs_setattr_nounix (direntry, attrs); +do { +if (pTcon->unix_ext) + rc =cifs_setattr_unix (direntry, attrs); +else + rc =cifs_setattr_nounix (direntry, attrs); + retries++; + }while (is_retryable_error (rc) && retries <2 );/* BB: add cifs_setattr_legacy for really old servers */ +return rc; }#if 0
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 164/391 arm64: dts: renesas: ulcb: add full-pwr-cycle-in-suspend into eMMC nodes
In reply to Greg Kroah-HartmanFrom: Yoshihiro Shimoda <[email protected]>
[ Upstream commit 992d7a8b88c83c05664b649fc54501ce58e19132 ]
Add full-pwr-cycle-in-suspend property to do a graceful shutdown of the eMMC device in system suspend.
--- arch/arm64/boot/dts/renesas/ulcb.dtsi | 1 + 1 file changed, 1 insertion(+)
arch/arm64/boot/dts/renesas/ulcb.dtsi +1 -0
@@ -469,6 +469,7 @@ mmc-hs200-1_8v; mmc-hs400-1_8v; non-removable; + full-pwr-cycle-in-suspend; status = "okay"; };
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 165/391 ARM: dts: omap4: Fix sgx clock rate for 4430
In reply to Greg Kroah-HartmanFrom: Tony Lindgren <[email protected]>
[ Upstream commit 19d3e9a0bdd57b90175f30390edeb06851f5f9f3 ]
We currently have a different clock rate for droid4 compared to the stock v3.0.8 based Android Linux kernel:
# cat /sys/kernel/debug/clk/dpll_*_m7x2_ck/clk_rate 266666667 307200000 # cat /sys/kernel/debug/clk/l3_gfx_cm:clk:0000:0/clk_rate 307200000
Let's fix this by configuring sgx to use 153.6 MHz instead of 307.2 MHz. Looks like also at least duover needs this change to avoid hangs, so let's apply it for all 4430.
This helps a bit with thermal issues that seem to be related to memory corruption when using sgx. It seems that other driver related issues still remain though.
--- arch/arm/boot/dts/omap4.dtsi | 2 +- arch/arm/boot/dts/omap443x.dtsi | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-)
arch/arm/boot/dts/omap4.dtsi +1 -1
@@ -410,7 +410,7 @@ status = "disabled"; }; - target-module@56000000 { + sgx_module: target-module@56000000 { compatible = "ti,sysc-omap4", "ti,sysc"; reg = <0x5600fe00 0x4>, <0x5600fe10 0x4>;
arch/arm/boot/dts/omap443x.dtsi +10 -0
@@ -74,3 +74,13 @@ }; /include/ "omap443x-clocks.dtsi" + +/* + * Use dpll_per for sgx at 153.6MHz like droid4 stock v3.0.8 Android kernel + */ +&sgx_module { + assigned-clocks = <&l3_gfx_clkctrl OMAP4_GPU_CLKCTRL 24>, + <&dpll_per_m7x2_ck>; + assigned-clock-rates = <0>, <153600000>; + assigned-clock-parents = <&dpll_per_m7x2_ck>; +};
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 166/391 memory: emif: Remove bogus debugfs error handling
In reply to Greg Kroah-HartmanFrom: Dan Carpenter <[email protected]>
[ Upstream commit fd22781648080cc400772b3c68aa6b059d2d5420 ]
Callers are generally not supposed to check the return values from debugfs functions. Debugfs functions never return NULL so this error handling will never trigger. (Historically debugfs functions used to return a mix of NULL and error pointers but it was eventually deemed too complicated for something which wasn't intended to be used in normal situations).
Delete all the error handling.
--- drivers/memory/emif.c | 33 +++++---------------------------- 1 file changed, 5 insertions(+), 28 deletions(-)
drivers/memory/emif.c +5 -28
@@ -163,35 +163,12 @@ static const struct file_operations emif_mr4_fops = { static int __init_or_module emif_debugfs_init(struct emif_data *emif) { -struct dentry *dentry; -int ret; - - dentry =debugfs_create_dir (dev_name (emif->dev),NULL ); -if (!dentry) { - ret = -ENOMEM ; - goto err0; - } - emif->debugfs_root = dentry; - - dentry =debugfs_create_file ("regcache_dump" ,S_IRUGO , - emif->debugfs_root, emif, &emif_regdump_fops); -if (!dentry) { - ret = -ENOMEM ; - goto err1; - } - - dentry =debugfs_create_file ("mr4" ,S_IRUGO , - emif->debugfs_root, emif, &emif_mr4_fops); -if (!dentry) { - ret = -ENOMEM ; - goto err1; - } - + emif->debugfs_root =debugfs_create_dir (dev_name (emif->dev),NULL ); +debugfs_create_file ("regcache_dump" ,S_IRUGO , emif->debugfs_root, emif, + &emif_regdump_fops); +debugfs_create_file ("mr4" ,S_IRUGO , emif->debugfs_root, emif, + &emif_mr4_fops);return 0 ; -err1: -debugfs_remove_recursive (emif->debugfs_root); -err0: -return ret; } static void __exit emif_debugfs_exit(struct emif_data *emif)
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 167/391 ARM: dts: s5pv210: Enable audio on Aries boards
In reply to Greg Kroah-HartmanFrom: Jonathan Bakker <[email protected]>
[ Upstream commit cd972fe90008adf49de0790250c1275480ac5cdc ]
Both the Galaxy S and the Fascinate4G have a WM8994 codec, but they differ slightly in their jack detection and micbias configuration.
--- arch/arm/boot/dts/s5pv210-aries.dtsi | 10 +++ arch/arm/boot/dts/s5pv210-fascinate4g.dts | 98 +++++++++++++++++++++++ arch/arm/boot/dts/s5pv210-galaxys.dts | 85 ++++++++++++++++++++ 3 files changed, 193 insertions(+)
arch/arm/boot/dts/s5pv210-aries.dtsi +10 -0
@@ -47,6 +47,11 @@ }; }; + bt_codec: bt_sco { + compatible = "linux,bt-sco"; + #sound-dai-cells = <0>; + }; + vibrator_pwr: regulator-fixed-0 { compatible = "regulator-fixed"; regulator-name = "vibrator-en";
@@ -624,6 +629,11 @@ }; }; +&i2s0 { + dmas = <&pdma0 9>, <&pdma0 10>, <&pdma0 11>; + status = "okay"; +}; + &mfc { memory-region = <&mfc_left>, <&mfc_right>; };
arch/arm/boot/dts/s5pv210-fascinate4g.dts +98 -0
116 lines not on this page · raw message
arch/arm/boot/dts/s5pv210-galaxys.dts +85 -0
109 lines not on this page · raw message
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 168/391 ARM: dts: s5pv210: remove DMA controller bus node name to fix dtschema warnings
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
[ Upstream commit ea4e792f3c8931fffec4d700cf6197d84e9f35a6 ]
There is no need to keep DMA controller nodes under AMBA bus node. Remove the "amba" node to fix dtschema warnings like:
amba: $nodename:0: 'amba' does not match '^([a-z][a-z0-9\\-]+-bus|bus|soc|axi|ahb|apb)(@[0-9a-f]+)?$'
--- arch/arm/boot/dts/s5pv210.dtsi | 49 +++++++++++++++------------------- 1 file changed, 21 insertions(+), 28 deletions(-)
arch/arm/boot/dts/s5pv210.dtsi +21 -28
@@ -128,35 +128,28 @@ }; }; - amba { - #address-cells = <1>; - #size-cells = <1>; - compatible = "simple-bus"; - ranges; - - pdma0: dma@e0900000 { - compatible = "arm,pl330", "arm,primecell"; - reg = <0xe0900000 0x1000>; - interrupt-parent = <&vic0>; - interrupts = <19>; - clocks = <&clocks CLK_PDMA0>; - clock-names = "apb_pclk"; - #dma-cells = <1>; - #dma-channels = <8>; - #dma-requests = <32>; - }; + pdma0: dma@e0900000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0xe0900000 0x1000>; + interrupt-parent = <&vic0>; + interrupts = <19>; + clocks = <&clocks CLK_PDMA0>; + clock-names = "apb_pclk"; + #dma-cells = <1>; + #dma-channels = <8>; + #dma-requests = <32>; + }; - pdma1: dma@e0a00000 { - compatible = "arm,pl330", "arm,primecell"; - reg = <0xe0a00000 0x1000>; - interrupt-parent = <&vic0>; - interrupts = <20>; - clocks = <&clocks CLK_PDMA1>; - clock-names = "apb_pclk"; - #dma-cells = <1>; - #dma-channels = <8>; - #dma-requests = <32>; - }; + pdma1: dma@e0a00000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0xe0a00000 0x1000>; + interrupt-parent = <&vic0>; + interrupts = <20>; + clocks = <&clocks CLK_PDMA1>; + clock-names = "apb_pclk"; + #dma-cells = <1>; + #dma-channels = <8>; + #dma-requests = <32>; }; adc: adc@e1700000 {
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 169/391 ARM: dts: s5pv210: move fixed clocks under root node
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
[ Upstream commit d38cae370e5f2094cbc38db3082b8e9509ae52ce ]
The fixed clocks are kept under dedicated 'external-clocks' node, thus a fake 'reg' was added. This is not correct with dtschema as fixed-clock binding does not have a 'reg' property. Moving fixed clocks out of 'soc' to root node fixes multiple dtbs_check warnings:
external-clocks: $nodename:0: 'external-clocks' does not match '^([a-z][a-z0-9\\-]+-bus|bus|soc|axi|ahb|apb)(@[0-9a-f]+)?$'
external-clocks: #size-cells:0:0: 0 is not one of [1, 2]
external-clocks: oscillator@0:reg:0: [0] is too short
external-clocks: oscillator@1:reg:0: [1] is too short
external-clocks: 'ranges' is a required property
oscillator@0: 'reg' does not match any of the regexes: 'pinctrl-[0-9]+'
--- arch/arm/boot/dts/s5pv210.dtsi | 36 +++++++++++++--------------------- 1 file changed, 14 insertions(+), 22 deletions(-)
arch/arm/boot/dts/s5pv210.dtsi +14 -22
@@ -52,34 +52,26 @@ }; }; + xxti: oscillator-0 { + compatible = "fixed-clock"; + clock-frequency = <0>; + clock-output-names = "xxti"; + #clock-cells = <0>; + }; + + xusbxti: oscillator-1 { + compatible = "fixed-clock"; + clock-frequency = <0>; + clock-output-names = "xusbxti"; + #clock-cells = <0>; + }; + soc { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; ranges; - external-clocks { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; - - xxti: oscillator@0 { - compatible = "fixed-clock"; - reg = <0>; - clock-frequency = <0>; - clock-output-names = "xxti"; - #clock-cells = <0>; - }; - - xusbxti: oscillator@1 { - compatible = "fixed-clock"; - reg = <1>; - clock-frequency = <0>; - clock-output-names = "xusbxti"; - #clock-cells = <0>; - }; - }; - onenand: onenand@b0600000 { compatible = "samsung,s5pv210-onenand"; reg = <0xb0600000 0x2000>,
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 170/391 ARM: dts: s5pv210: move PMU node out of clock controller
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
[ Upstream commit bb98fff84ad1ea321823759edaba573a16fa02bd ]
The Power Management Unit (PMU) is a separate device which has little common with clock controller. Moving it to one level up (from clock controller child to SoC) allows to remove fake simple-bus compatible and dtbs_check warnings like:
clock-controller@e0100000: $nodename:0:
'clock-controller@e0100000' does not match '^([a-z][a-z0-9\\-]+-bus|bus|soc|axi|ahb|apb)(@[0-9a-f]+)?$'
--- arch/arm/boot/dts/s5pv210.dtsi | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-)
arch/arm/boot/dts/s5pv210.dtsi +5 -8
@@ -92,19 +92,16 @@ }; clocks: clock-controller@e0100000 { - compatible = "samsung,s5pv210-clock", "simple-bus"; + compatible = "samsung,s5pv210-clock"; reg = <0xe0100000 0x10000>; clock-names = "xxti", "xusbxti"; clocks = <&xxti>, <&xusbxti>; #clock-cells = <1>; - #address-cells = <1>; - #size-cells = <1>; - ranges; + }; - pmu_syscon: syscon@e0108000 { - compatible = "samsung-s5pv210-pmu", "syscon"; - reg = <0xe0108000 0x8000>; - }; + pmu_syscon: syscon@e0108000 { + compatible = "samsung-s5pv210-pmu", "syscon"; + reg = <0xe0108000 0x8000>; }; pinctrl0: pinctrl@e0200000 {
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 171/391 ARM: dts: s5pv210: remove dedicated audio-subsystem node
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
[ Upstream commit 6c17a2974abf68a58517f75741b15c4aba42b4b8 ]
The 'audio-subsystem' node is an artificial creation, not representing real hardware. The hardware is described by its nodes - AUDSS clock controller and I2S0.
Remove the 'audio-subsystem' node along with its undocumented compatible to fix dtbs_check warnings like:
audio-subsystem: $nodename:0: 'audio-subsystem' does not match '^([a-z][a-z0-9\\-]+-bus|bus|soc|axi|ahb|apb)(@[0-9a-f]+)?$'
--- arch/arm/boot/dts/s5pv210.dtsi | 65 +++++++++++++++------------------- 1 file changed, 29 insertions(+), 36 deletions(-)
arch/arm/boot/dts/s5pv210.dtsi +29 -36
@@ -223,43 +223,36 @@ status = "disabled"; }; - audio-subsystem { - compatible = "samsung,s5pv210-audss", "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - clk_audss: clock-controller@eee10000 { - compatible = "samsung,s5pv210-audss-clock"; - reg = <0xeee10000 0x1000>; - clock-names = "hclk", "xxti", - "fout_epll", - "sclk_audio0"; - clocks = <&clocks DOUT_HCLKP>, <&xxti>, - <&clocks FOUT_EPLL>, - <&clocks SCLK_AUDIO0>; - #clock-cells = <1>; - }; + clk_audss: clock-controller@eee10000 { + compatible = "samsung,s5pv210-audss-clock"; + reg = <0xeee10000 0x1000>; + clock-names = "hclk", "xxti", + "fout_epll", + "sclk_audio0"; + clocks = <&clocks DOUT_HCLKP>, <&xxti>, + <&clocks FOUT_EPLL>, + <&clocks SCLK_AUDIO0>; + #clock-cells = <1>; + }; - i2s0: i2s@eee30000 { - compatible = "samsung,s5pv210-i2s"; - reg = <0xeee30000 0x1000>; - interrupt-parent = <&vic2>; - interrupts = <16>; - dma-names = "rx", "tx", "tx-sec"; - dmas = <&pdma1 9>, <&pdma1 10>, <&pdma1 11>; - clock-names = "iis", - "i2s_opclk0", - "i2s_opclk1"; - clocks = <&clk_audss CLK_I2S>, - <&clk_audss CLK_I2S>, - <&clk_audss CLK_DOUT_AUD_BUS>; - samsung,idma-addr = <0xc0010000>; - pinctrl-names = "default"; - pinctrl-0 = <&i2s0_bus>; - #sound-dai-cells = <0>; - status = "disabled"; - }; + i2s0: i2s@eee30000 { + compatible = "samsung,s5pv210-i2s"; + reg = <0xeee30000 0x1000>; + interrupt-parent = <&vic2>; + interrupts = <16>; + dma-names = "rx", "tx", "tx-sec"; + dmas = <&pdma1 9>, <&pdma1 10>, <&pdma1 11>; + clock-names = "iis", + "i2s_opclk0", + "i2s_opclk1"; + clocks = <&clk_audss CLK_I2S>, + <&clk_audss CLK_I2S>, + <&clk_audss CLK_DOUT_AUD_BUS>; + samsung,idma-addr = <0xc0010000>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s0_bus>; + #sound-dai-cells = <0>; + status = "disabled"; }; i2s1: i2s@e2100000 {
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 172/391 ARM: dts: s5pv210: add RTC 32 KHz clock in Aries family
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
[ Upstream commit 086c4498b0cc87fdb09188f3da7056e898814948 ]
The S3C RTC requires 32768 Hz clock as input which is provided by PMIC. However there is no such clock provider but rather a regulator driver which registers the clock as a regulator. This is an old driver which will not be updated so add a workaround - a fixed-clock to fill missing clock phandle reference in S3C RTC.
This fixes dtbs_check warnings:
rtc@e2800000: clocks: [[2, 145]] is too short
rtc@e2800000: clock-names: ['rtc'] is too short
--- arch/arm/boot/dts/s5pv210-aries.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+)
arch/arm/boot/dts/s5pv210-aries.dtsi +12 -0
@@ -47,6 +47,13 @@ }; }; + pmic_ap_clk: clock-0 { + /* Workaround for missing clock on PMIC */ + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + }; + bt_codec: bt_sco { compatible = "linux,bt-sco"; #sound-dai-cells = <0>;
@@ -825,6 +832,11 @@ samsung,pwm-outputs = <1>; }; +&rtc { + clocks = <&clocks CLK_RTC>, <&pmic_ap_clk>; + clock-names = "rtc", "rtc_src"; +}; + &sdhci1 { #address-cells = <1>; #size-cells = <0>;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 173/391 ARM: dts: s5pv210: align SPI GPIO node name with dtschema in Aries
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
[ Upstream commit 1ed7f6d0bab2f1794f1eb4ed032e90575552fd21 ]
The device tree schema expects SPI controller to be named "spi", otherwise dtbs_check complain with a warning like:
spi-gpio-0: $nodename:0: 'spi-gpio-0' does not match '^spi(@.*|-[0-9a-f])*$'
--- arch/arm/boot/dts/s5pv210-aries.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/boot/dts/s5pv210-aries.dtsi +1 -1
@@ -545,7 +545,7 @@ value = <0x5200>; }; - spi_lcd: spi-gpio-0 { + spi_lcd: spi-2 { compatible = "spi-gpio"; #address-cells = <1>; #size-cells = <0>;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 174/391 soc: qcom: rpmh-rsc: Sleep waiting for tcs slots to be free
In reply to Greg Kroah-HartmanFrom: Stephen Boyd <[email protected]>
[ Upstream commit 2bc20f3c8487bd5bc4dd9ad2c06d2ba05fd4e838 ]
The busy loop in rpmh_rsc_send_data() is written with the assumption that the udelay will be preempted by the tcs_tx_done() irq handler when the TCS slots are all full. This doesn't hold true when the calling thread is an irqthread and the tcs_tx_done() irq is also an irqthread. That's because kernel irqthreads are SCHED_FIFO and thus need to voluntarily give up priority by calling into the scheduler so that other threads can run.
I see RCU stalls when I boot with irqthreads on the kernel commandline because the modem remoteproc driver is trying to send an rpmh async message from an irqthread that needs to give up the CPU for the rpmh irqthread to run and clear out tcs slots.
rcu: INFO: rcu_preempt self-detected stall on CPU rcu: 0-....: (1 GPs behind) idle=402/1/0x4000000000000002 softirq=2108/2109 fqs=4920 (t=21016 jiffies g=2933 q=590) Task dump for CPU 0: irq/11-smp2p R running task 0 148 2 0x00000028 Call trace: dump_backtrace+0x0/0x154 show_stack+0x20/0x2c sched_show_task+0xfc/0x108 dump_cpu_task+0x44/0x50 rcu_dump_cpu_stacks+0xa4/0xf8 rcu_sched_clock_irq+0x7dc/0xaa8 update_process_times+0x30/0x54 tick_sched_handle+0x50/0x64 tick_sched_timer+0x4c/0x8c __hrtimer_run_queues+0x21c/0x36c hrtimer_interrupt+0xf0/0x22c arch_timer_handler_phys+0x40/0x50 handle_percpu_devid_irq+0x114/0x25c __handle_domain_irq+0x84/0xc4 gic_handle_irq+0xd0/0x178 el1_irq+0xbc/0x180 save_return_addr+0x18/0x28 return_address+0x54/0x88 preempt_count_sub+0x40/0x88 _raw_spin_unlock_irqrestore+0x4c/0x6c ___ratelimit+0xd0/0x128 rpmh_rsc_send_data+0x24c/0x378 __rpmh_write+0x1b0/0x208 rpmh_write_async+0x90/0xbc rpmhpd_send_corner+0x60/0x8c rpmhpd_aggregate_corner+0x8c/0x124 rpmhpd_set_performance_state+0x8c/0xbc _genpd_set_performance_state+0xdc/0x1b8 dev_pm_genpd_set_performance_state+0xb8/0xf8 q6v5_pds_disable+0x34/0x60 [qcom_q6v5_mss] qcom_msa_handover+0x38/0x44 [qcom_q6v5_mss] q6v5_handover_interrupt+0x24/0x3c [qcom_q6v5] handle_nested_irq+0xd0/0x138 qcom_smp2p_intr+0x188/0x200 irq_thread_fn+0x2c/0x70 irq_thread+0xfc/0x14c kthread+0x11c/0x12c ret_from_fork+0x10/0x18
This busy loop naturally lends itself to using a wait queue so that each thread that tries to send a message will sleep waiting on the waitqueue and only be woken up when a free slot is available. This should make things more predictable too because the scheduler will be able to sleep tasks that are waiting on a free tcs instead of the busy loop we currently have today.
--- drivers/soc/qcom/rpmh-internal.h | 4 ++ drivers/soc/qcom/rpmh-rsc.c | 115 +++++++++++++++---------------- 2 files changed, 58 insertions(+), 61 deletions(-)
drivers/soc/qcom/rpmh-internal.h +4 -0
@@ -8,6 +8,7 @@#define __RPM_INTERNAL_H__#include <linux/bitmap.h> +#include <linux/wait.h> #include <soc/qcom/tcs.h> #define TCS_TYPE_NR 4
@@ -106,6 +107,8 @@ struct rpmh_ctrlr {* @lock: Synchronize state of the controller. If RPMH's cache * lock will also be held, the order is: drv->lock then * cache_lock. +* @tcs_wait: Wait queue used to wait for @tcs_in_use to free up a +* slot * @client: Handle to the DRV's client. */ struct rsc_drv {
@@ -118,6 +121,7 @@ struct rsc_drv {struct tcs_group tcs[TCS_TYPE_NR ];DECLARE_BITMAP (tcs_in_use,MAX_TCS_NR );spinlock_t lock; +wait_queue_head_t tcs_wait;struct rpmh_ctrlr client; };
drivers/soc/qcom/rpmh-rsc.c +54 -61
163 lines not on this page · raw message
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 175/391 soc: ti: k3: ringacc: add am65x sr2.0 support
In reply to Greg Kroah-HartmanFrom: Grygorii Strashko <[email protected]>
[ Upstream commit 95e7be062aea6d2e09116cd4d28957d310c04781 ]
The AM65x SR2.0 Ringacc has fixed errata i2023 "RINGACC, UDMA: RINGACC and UDMA Ring State Interoperability Issue after Channel Teardown". This errata also fixed for J271E SoC.
Use SOC bus data for K3 SoC identification and enable i2023 errate w/a only for the AM65x SR1.0. This also makes obsolete "ti,dma-ring-reset-quirk" DT property.
--- drivers/soc/ti/k3-ringacc.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-)
drivers/soc/ti/k3-ringacc.c +30 -3
@@ -10,6 +10,7 @@#include <linux/init.h> #include <linux/of.h> #include <linux/platform_device.h> +#include <linux/sys_soc.h> #include <linux/soc/ti/k3-ringacc.h> #include <linux/soc/ti/ti_sci_protocol.h> #include <linux/soc/ti/ti_sci_inta_msi.h>
@@ -208,6 +209,15 @@ struct k3_ringacc {const struct k3_ringacc_ops *ops; }; +/** +* struct k3_ringacc - Rings accelerator SoC data +* +* @dma_ring_reset_quirk: DMA reset w/a enable +*/ +struct k3_ringacc_soc_data { +unsigned dma_ring_reset_quirk:1 ; +}; +static long k3_ringacc_ring_get_fifo_pos (struct k3_ring *ring) { return K3_RINGACC_FIFO_WINDOW_SIZE_BYTES -
@@ -1051,9 +1061,6 @@ static int k3_ringacc_probe_dt(struct k3_ringacc *ringacc)return ret; } - ringacc->dma_ring_reset_quirk = -of_property_read_bool (node,"ti,dma-ring-reset-quirk" ); - ringacc->tisci =ti_sci_get_by_phandle (node,"ti,sci" );if (IS_ERR (ringacc->tisci)) { ret =PTR_ERR (ringacc->tisci);
@@ -1084,9 +1091,22 @@ static int k3_ringacc_probe_dt(struct k3_ringacc *ringacc) ringacc->rm_gp_range); } +static const struct k3_ringacc_soc_data k3_ringacc_soc_data_sr1 = { + .dma_ring_reset_quirk =1 , +}; + +static const struct soc_device_attribute k3_ringacc_socinfo[] = { + { .family ="AM65X" , + .revision ="SR1.0" , + .data = &k3_ringacc_soc_data_sr1 + }, + {/* sentinel */ } +}; +static int k3_ringacc_init (struct platform_device *pdev,struct k3_ringacc *ringacc) { +const struct soc_device_attribute *soc;void __iomem *base_fifo, *base_rt;struct device *dev = &pdev->dev;struct resource *res;
@@ -1103,6 +1123,13 @@ static int k3_ringacc_init(struct platform_device *pdev,if (ret)return ret; + soc =soc_device_match (k3_ringacc_socinfo); +if (soc && soc->data) { +const struct k3_ringacc_soc_data *soc_data = soc->data; + + ringacc->dma_ring_reset_quirk = soc_data->dma_ring_reset_quirk; + } + res =platform_get_resource_byname (pdev,IORESOURCE_MEM ,"rt" ); base_rt =devm_ioremap_resource (dev, res);if (IS_ERR (base_rt))
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 176/391 bindings: soc: ti: soc: ringacc: remove ti,dma-ring-reset-quirk
In reply to Greg Kroah-HartmanFrom: Grygorii Strashko <[email protected]>
[ Upstream commit aee123f48f387ea62002cddb46c7cb04c96628df ]
Remove "ti,dma-ring-reset-quirk" DT property as proper w/a handling is implemented now in Ringacc driver using SoC info.
--- Documentation/devicetree/bindings/soc/ti/k3-ringacc.yaml | 6 ------ 1 file changed, 6 deletions(-)
Documentation/devicetree/bindings/soc/ti/k3-ringacc.yaml +0 -6
@@ -62,11 +62,6 @@ properties: $ref: /schemas/types.yaml#/definitions/uint32 description: TI-SCI device id of the ring accelerator - ti,dma-ring-reset-quirk: - $ref: /schemas/types.yaml#definitions/flag - description: | - enable ringacc/udma ring state interoperability issue software w/a - required: - compatible - reg
@@ -94,7 +89,6 @@ examples: reg-names = "rt", "fifos", "proxy_gcfg", "proxy_target"; ti,num-rings = <818>; ti,sci-rm-range-gp-rings = <0x2>; /* GP ring range */ - ti,dma-ring-reset-quirk; ti,sci = <&dmsc>; ti,sci-dev-id = <187>; msi-parent = <&inta_main_udmass>;
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 177/391 firmware: arm_scmi: Move scmi bus init and exit calls into the driver
In reply to Greg Kroah-HartmanFrom: Sudeep Holla <[email protected]>
[ Upstream commit 5a2f0a0bdf201e2183904b6217f9c74774c961a8 ]
In preparation to enable building scmi as a single module, let us move the scmi bus {de-,}initialisation call into the driver.
The main reason for this is to keep it simple instead of maintaining it as separate modules and dealing with all possible initcall races and deferred probe handling. We can move it as separate modules if needed in future.
--- drivers/firmware/arm_scmi/bus.c | 6 ++---- drivers/firmware/arm_scmi/common.h | 3 +++ drivers/firmware/arm_scmi/driver.c | 16 +++++++++++++++- 3 files changed, 20 insertions(+), 5 deletions(-)
drivers/firmware/arm_scmi/bus.c +2 -4
@@ -230,7 +230,7 @@ static void scmi_devices_unregister(void)bus_for_each_dev (&scmi_bus_type,NULL ,NULL , __scmi_devices_unregister); } -static int __init scmi_bus_init (void ) +int __init scmi_bus_init (void ) {int retval;
@@ -240,12 +240,10 @@ static int __init scmi_bus_init(void)return retval; } -subsys_initcall (scmi_bus_init); -static void __exit scmi_bus_exit(void) +void __exit scmi_bus_exit(void) {scmi_devices_unregister ();bus_unregister (&scmi_bus_type);ida_destroy (&scmi_bus_id); } -module_exit (scmi_bus_exit);
drivers/firmware/arm_scmi/common.h +3 -0
@@ -158,6 +158,9 @@ void scmi_setup_protocol_implemented(const struct scmi_handle *handle,int scmi_base_protocol_init (struct scmi_handle *h); +int __init scmi_bus_init (void ); +void __exit scmi_bus_exit(void); +/* SCMI Transport */ /** * struct scmi_chan_info - Structure representing a SCMI channel information
drivers/firmware/arm_scmi/driver.c +15 -1
@@ -936,7 +936,21 @@ static struct platform_driver scmi_driver = { .remove = scmi_remove, }; -module_platform_driver (scmi_driver); +static int __init scmi_driver_init (void ) +{ +scmi_bus_init (); + +return platform_driver_register (&scmi_driver); +} +module_init (scmi_driver_init); + +static void __exit scmi_driver_exit(void) +{ +scmi_bus_exit (); + +platform_driver_unregister (&scmi_driver); +} +module_exit (scmi_driver_exit);MODULE_ALIAS ("platform: arm-scmi" );MODULE_AUTHOR ("Sudeep Holla <[email protected]>" );
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 178/391 arm64: dts: qcom: kitakami: Temporarily disable SDHCI1
In reply to Greg Kroah-HartmanFrom: Konrad Dybcio <[email protected]>
[ Upstream commit e884fb6cc89dce1debeae33704edd7735a3d6d9c ]
There is an issue with Kitakami eMMCs dying when a quirk isn't addressed. Until that happens, disable it.
--- arch/arm64/boot/dts/qcom/msm8994-sony-xperia-kitakami.dtsi | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
arch/arm64/boot/dts/qcom/msm8994-sony-xperia-kitakami.dtsi +6 -1
@@ -221,7 +221,12 @@ }; &sdhc1 { - status = "okay"; + /* There is an issue with the eMMC causing permanent + * damage to the card if a quirk isn't addressed. + * Until it's fixed, disable the MMC so as not to brick + * devices. + */ + status = "disabled"; /* Downstream pushes 2.95V to the sdhci device, * but upstream driver REALLY wants to make vmmc 1.8v
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 179/391 nbd: make the config put is called before the notifying the waiter
In reply to Greg Kroah-HartmanFrom: Xiubo Li <[email protected]>
[ Upstream commit 87aac3a80af5cbad93e63250e8a1e19095ba0d30 ]
There has one race case for ceph's rbd-nbd tool. When do mapping it may fail with EBUSY from ioctl(nbd, NBD_DO_IT), but actually the nbd device has already unmaped.
It dues to if just after the wake_up(), the recv_work() is scheduled out and defers calling the nbd_config_put(), though the map process has exited the "nbd->recv_task" is not cleared.
--- drivers/block/nbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/block/nbd.c +1 -1
@@ -801,9 +801,9 @@ static void recv_work(struct work_struct *work)if (likely (!blk_should_fake_timeout (rq->q)))blk_mq_complete_request (rq); } +nbd_config_put (nbd);atomic_dec (&config->recv_threads);wake_up (&config->recv_wq); -nbd_config_put (nbd);kfree (args); }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 180/391 sgl_alloc_order: fix memory leak
In reply to Greg Kroah-HartmanFrom: Douglas Gilbert <[email protected]>
[ Upstream commit b2a182a40278bc5849730e66bca01a762188ed86 ]
sgl_alloc_order() can fail when 'length' is large on a memory constrained system. When order > 0 it will potentially be making several multi-page allocations with the later ones more likely to fail than the earlier one. So it is important that sgl_alloc_order() frees up any pages it has obtained before returning NULL. In the case when order > 0 it calls the wrong free page function and leaks. In testing the leak was sufficient to bring down my 8 GiB laptop with OOM.
--- lib/scatterlist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
lib/scatterlist.c +1 -1
@@ -514,7 +514,7 @@ struct scatterlist *sgl_alloc_order(unsigned long long length, elem_len =min_t (u64, length,PAGE_SIZE << order); page =alloc_pages (gfp, order);if (!page) { -sgl_free (sgl); +sgl_free_order (sgl, order);return NULL ; }
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 181/391 nvme-rdma: fix crash when connect rejected
In reply to Greg Kroah-HartmanFrom: Chao Leng <[email protected]>
[ Upstream commit 43efdb8e870ee0f58633fd579aa5b5185bf5d39e ]
A crash can happened when a connect is rejected. The host establishes
the connection after received ConnectReply, and then continues to send the fabrics Connect command. If the controller does not receive the ReadyToUse capsule, host may receive a ConnectReject reply.
Call nvme_rdma_destroy_queue_ib after the host received the RDMA_CM_EVENT_REJECTED event. Then when the fabrics Connect command times out, nvme_rdma_timeout calls nvme_rdma_complete_rq to fail the request. A crash happenes due to use after free in nvme_rdma_complete_rq.
nvme_rdma_destroy_queue_ib is redundant when handling the RDMA_CM_EVENT_REJECTED event as nvme_rdma_destroy_queue_ib is already called in connection failure handler.
--- drivers/nvme/host/rdma.c | 1 - 1 file changed, 1 deletion(-)
drivers/nvme/host/rdma.c +0 -1
@@ -1926,7 +1926,6 @@ static int nvme_rdma_cm_handler(struct rdma_cm_id *cm_id,complete (&queue->cm_done);return 0 ;case RDMA_CM_EVENT_REJECTED : -nvme_rdma_destroy_queue_ib (queue); cm_error =nvme_rdma_conn_rejected (queue, ev);break ;case RDMA_CM_EVENT_ROUTE_ERROR :
Signature · 1 line
2.27.0
Greg Kroah-Hartman
maintainerPATCH 182/391 vmlinux.lds.h: Add PGO and AutoFDO input sections
In reply to Greg Kroah-HartmanFrom: Nick Desaulniers <[email protected]>
commit eff8728fe69880d3f7983bec3fb6cea4c306261f upstream.
Basically, consider .text.{hot|unlikely|unknown}.* part of .text, too.
When compiling with profiling information (collected via PGO instrumentations or AutoFDO sampling), Clang will separate code into .text.hot, .text.unlikely, or .text.unknown sections based on profiling information. After D79600 (clang-11), these sections will have a trailing . suffix, ie. .text.hot., .text.unlikely., .text.unknown..
When using -ffunction-sections together with profiling infomation, either explicitly (FGKASLR) or implicitly (LTO), code may be placed in sections following the convention:
.text.hot.<foo>, .text.unlikely.<bar>, .text.unknown.<baz> where <foo>, <bar>, and <baz> are functions. (This produces one section per function; we generally try to merge these all back via linker script so that we don't have 50k sections).
For the above cases, we need to teach our linker scripts that such sections might exist and that we'd explicitly like them grouped together, otherwise we can wind up with code outside of the _stext/_etext boundaries that might not be mapped properly for some architectures, resulting in boot failures.
If the linker script is not told about possible input sections, then where the section is placed as output is a heuristic-laiden mess that's non-portable between linkers (ie. BFD and LLD), and has resulted in many hard to debug bugs. Kees Cook is working on cleaning this up by adding --orphan-handling=warn linker flag used in ARCH=powerpc to additional architectures. In the case of linker scripts, borrowing from the Zen of
Python: explicit is better than implicit.
Also, ld.bfd's internal linker script considers .text.hot AND .text.hot.* to be part of .text, as well as .text.unlikely and .text.unlikely.*. I didn't see support for .text.unknown.*, and didn't see Clang producing such code in our kernel builds, but I see code in LLVM that can produce such section names if profiling information is missing. That may point to a larger issue with generating or collecting profiles, but I would much rather be safe and explicit than have to debug yet another issue related to orphan section placement.
--- include/asm-generic/vmlinux.lds.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
include/asm-generic/vmlinux.lds.h +4 -1
@@ -581,7 +581,10 @@*/ #define TEXT_TEXT \ ALIGN_FUNCTION(); \ - *(.text.hot TEXT_MAIN .text.fixup .text.unlikely) \ + *(.text.hot .text.hot.*) \ + *(TEXT_MAIN .text.fixup) \ + *(.text.unlikely .text.unlikely.*) \ + *(.text.unknown .text.unknown.*) \ NOINSTR_TEXT \ *(.text..refcount) \ *(.ref.text) \
Greg Kroah-Hartman
maintainerPATCH 183/391 irqchip/loongson-htvec: Fix initial interrupt clearing
In reply to Greg Kroah-HartmanFrom: Huacai Chen <[email protected]>
commit 1d1e5630de78f7253ac24b92cee6427c3ff04d56 upstream.
In htvec_reset() only the first group of initial interrupts is cleared. This sometimes causes spurious interrupts, so let's clear all groups.
While at it, fix the nearby comment that to match the reality of what the driver does.
--- drivers/irqchip/irq-loongson-htvec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/irqchip/irq-loongson-htvec.c +2 -2
@@ -151,7 +151,7 @@ static void htvec_reset(struct htvec *pr/* Clear IRQ cause registers, mask all interrupts */ for (idx =0 ; idx < priv->num_parents; idx++) {writel_relaxed (0x0 , priv->base +HTVEC_EN_OFF +4 * idx); -writel_relaxed (0xFFFFFFFF , priv->base); +writel_relaxed (0xFFFFFFFF , priv->base +4 * idx); } }
@@ -172,7 +172,7 @@ static int htvec_of_init(struct device_n goto free_priv; } -/* Interrupt may come from any of the 4 interrupt line */ +/* Interrupt may come from any of the 8 interrupt lines */ for (i =0 ; i <HTVEC_MAX_PARENT_IRQ ; i++) { parent_irq[i] =irq_of_parse_and_map (node, i);if (parent_irq[i] <=0 )
Greg Kroah-Hartman
maintainerPATCH 184/391 md: fix the checking of wrong work queue
In reply to Greg Kroah-HartmanFrom: Guoqing Jiang <[email protected]>
commit cf0b9b4821a2955f8a23813ef8f422208ced9bd7 upstream.
It should check md_rdev_misc_wq instead of md_misc_wq.
--- drivers/md/md.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/md/md.c +1 -1
@@ -9545,7 +9545,7 @@ static int __init md_init(void) goto err_misc_wq; md_rdev_misc_wq =alloc_workqueue ("md_rdev_misc" ,0 ,0 ); -if (!md_misc_wq) +if (!md_rdev_misc_wq) goto err_rdev_misc_wq;if ((ret =register_blkdev (MD_MAJOR ,"md" )) <0 )
Greg Kroah-Hartman
maintainerPATCH 185/391 md/raid5: fix oops during stripe resizing
In reply to Greg Kroah-HartmanFrom: Song Liu <[email protected]>
commit b44c018cdf748b96b676ba09fdbc5b34fc443ada upstream.
KoWei reported crash during raid5 reshape:
[ 1032.252932] Oops: 0002 [#1] SMP PTI [...] [ 1032.252943] RIP: 0010:memcpy_erms+0x6/0x10 [...] [ 1032.252947] RSP: 0018:ffffba1ac0c03b78 EFLAGS: 00010286 [ 1032.252949] RAX: 0000784ac0000000 RBX: ffff91bec3d09740 RCX: 0000000000001000 [ 1032.252951] RDX: 0000000000001000 RSI: ffff91be6781c000 RDI: 0000784ac0000000 [ 1032.252953] RBP: ffffba1ac0c03bd8 R08: 0000000000001000 R09: ffffba1ac0c03bf8 [ 1032.252954] R10: 0000000000000000 R11: 0000000000000000 R12: ffffba1ac0c03bf8 [ 1032.252955] R13: 0000000000001000 R14: 0000000000000000 R15: 0000000000000000 [ 1032.252958] FS: 0000000000000000(0000) GS:ffff91becf500000(0000) knlGS:0000000000000000 [ 1032.252959] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1032.252961] CR2: 0000784ac0000000 CR3: 000000031780a002 CR4: 00000000001606e0 [ 1032.252962] Call Trace: [ 1032.252969] ? async_memcpy+0x179/0x1000 [async_memcpy] [ 1032.252977] ? raid5_release_stripe+0x8e/0x110 [raid456] [ 1032.252982] handle_stripe_expansion+0x15a/0x1f0 [raid456] [ 1032.252988] handle_stripe+0x592/0x1270 [raid456] [ 1032.252993] handle_active_stripes.isra.0+0x3cb/0x5a0 [raid456] [ 1032.252999] raid5d+0x35c/0x550 [raid456] [ 1032.253002] ? schedule+0x42/0xb0 [ 1032.253006] ? schedule_timeout+0x10e/0x160 [ 1032.253011] md_thread+0x97/0x160 [ 1032.253015] ? wait_woken+0x80/0x80 [ 1032.253019] kthread+0x104/0x140 [ 1032.253022] ? md_start_sync+0x60/0x60 [ 1032.253024] ? kthread_park+0x90/0x90 [ 1032.253027] ret_from_fork+0x35/0x40
This is because cache_size_mutex was unlocked too early in resize_stripes, which races with grow_one_stripe() that grow_one_stripe() allocates a stripe with wrong pool_size.
Fix this issue by unlocking cache_size_mutex after updating pool_size.
--- drivers/md/raid5.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/md/raid5.c +2 -2
@@ -2429,8 +2429,6 @@ static int resize_stripes(struct r5conf }else err = -ENOMEM ; -mutex_unlock (&conf->cache_size_mutex); - conf->slab_cache = sc; conf->active_name =1 -conf->active_name;
@@ -2453,6 +2451,8 @@ static int resize_stripes(struct r5confif (!err) conf->pool_size = newsize; +mutex_unlock (&conf->cache_size_mutex); +return err; }
Greg Kroah-Hartman
maintainerPATCH 186/391 mmc: sdhci: Add LTR support for some Intel BYT based controllers
In reply to Greg Kroah-HartmanFrom: Adrian Hunter <[email protected]>
commit 46f4a69ec8ed6ab9f6a6172afe50df792c8bc1b6 upstream.
Some Intel BYT based host controllers support the setting of latency tolerance. Accordingly, implement the PM QoS ->set_latency_tolerance() callback. The raw register values are also exposed via debugfs.
Intel EHL controllers require this support.
--- drivers/mmc/host/sdhci-pci-core.c | 154 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+)
drivers/mmc/host/sdhci-pci-core.c +154 -0
@@ -24,6 +24,8 @@#include <linux/iopoll.h> #include <linux/gpio.h> #include <linux/pm_runtime.h> +#include <linux/pm_qos.h> +#include <linux/debugfs.h> #include <linux/mmc/slot-gpio.h> #include <linux/mmc/sdhci-pci-data.h> #include <linux/acpi.h>
@@ -516,6 +518,8 @@ struct intel_host {bool rpm_retune_ok;u32 glk_rx_ctrl1;u32 glk_tun_val; +u32 active_ltr; +u32 idle_ltr; }; static const guid_t intel_dsm_guid =
@@ -760,6 +764,108 @@ static int intel_execute_tuning(struct mreturn 0 ; } +#define INTEL_ACTIVELTR 0x804 +#define INTEL_IDLELTR 0x808 + +#define INTEL_LTR_REQ BIT(15) +#define INTEL_LTR_SCALE_MASK GENMASK(11, 10) +#define INTEL_LTR_SCALE_1US (2 << 10) +#define INTEL_LTR_SCALE_32US (3 << 10) +#define INTEL_LTR_VALUE_MASK GENMASK(9, 0) + +static void intel_cache_ltr (struct sdhci_pci_slot *slot) +{ +struct intel_host *intel_host =sdhci_pci_priv (slot); +struct sdhci_host *host = slot->host; + + intel_host->active_ltr =readl (host->ioaddr +INTEL_ACTIVELTR ); + intel_host->idle_ltr =readl (host->ioaddr +INTEL_IDLELTR ); +} + +static void intel_ltr_set (struct device *dev,s32 val) +{ +struct sdhci_pci_chip *chip =dev_get_drvdata (dev); +struct sdhci_pci_slot *slot = chip->slots[0 ]; +struct intel_host *intel_host =sdhci_pci_priv (slot); +struct sdhci_host *host = slot->host; +u32 ltr; + +pm_runtime_get_sync (dev); + +/* +* Program latency tolerance (LTR) accordingly what has been asked +* by the PM QoS layer or disable it in case we were passed +* negative value or PM_QOS_LATENCY_ANY. +*/ + ltr =readl (host->ioaddr +INTEL_ACTIVELTR ); + +if (val ==PM_QOS_LATENCY_ANY || val <0 ) { + ltr &= ~INTEL_LTR_REQ ; + }else { + ltr |=INTEL_LTR_REQ ; + ltr &= ~INTEL_LTR_SCALE_MASK ; + ltr &= ~INTEL_LTR_VALUE_MASK ; + +if (val >INTEL_LTR_VALUE_MASK ) { + val >>=5 ; +if (val >INTEL_LTR_VALUE_MASK ) + val =INTEL_LTR_VALUE_MASK ; + ltr |=INTEL_LTR_SCALE_32US | val; + }else { + ltr |=INTEL_LTR_SCALE_1US | val; + } + } + +if (ltr == intel_host->active_ltr) + goto out; + +writel (ltr, host->ioaddr +INTEL_ACTIVELTR ); +writel (ltr, host->ioaddr +INTEL_IDLELTR ); + +/* Cache the values into lpss structure */ +intel_cache_ltr (slot); +out: +pm_runtime_put_autosuspend (dev); +} + +static bool intel_use_ltr (struct sdhci_pci_chip *chip) +{ +switch (chip->pdev->device) { +case PCI_DEVICE_ID_INTEL_BYT_EMMC : +case PCI_DEVICE_ID_INTEL_BYT_EMMC2 : +case PCI_DEVICE_ID_INTEL_BYT_SDIO : +case PCI_DEVICE_ID_INTEL_BYT_SD : +case PCI_DEVICE_ID_INTEL_BSW_EMMC : +case PCI_DEVICE_ID_INTEL_BSW_SDIO : +case PCI_DEVICE_ID_INTEL_BSW_SD : +return false; +default : +return true; + } +} + +static void intel_ltr_expose (struct sdhci_pci_chip *chip) +{ +struct device *dev = &chip->pdev->dev; + +if (!intel_use_ltr (chip)) +return ; + + dev->power.set_latency_tolerance = intel_ltr_set; +dev_pm_qos_expose_latency_tolerance (dev); +} + +static void intel_ltr_hide (struct sdhci_pci_chip *chip) +{ +struct device *dev = &chip->pdev->dev; + +if (!intel_use_ltr (chip)) +return ; + +dev_pm_qos_hide_latency_tolerance (dev); + dev->power.set_latency_tolerance =NULL ; +} +static void byt_probe_slot (struct sdhci_pci_slot *slot) {struct mmc_host_ops *ops = &slot->host->mmc_host_ops;
@@ -774,6 +880,43 @@ static void byt_probe_slot(struct sdhci_ ops->start_signal_voltage_switch = intel_start_signal_voltage_switch;device_property_read_u32 (dev,"max-frequency" , &mmc->f_max); + +if (!mmc->slotno) { + slot->chip->slots[mmc->slotno] = slot; +intel_ltr_expose (slot->chip); + } +} + +static void byt_add_debugfs (struct sdhci_pci_slot *slot) +{ +struct intel_host *intel_host =sdhci_pci_priv (slot); +struct mmc_host *mmc = slot->host->mmc; +struct dentry *dir = mmc->debugfs_root; + +if (!intel_use_ltr (slot->chip)) +return ; + +debugfs_create_x32 ("active_ltr" ,0444 , dir, &intel_host->active_ltr); +debugfs_create_x32 ("idle_ltr" ,0444 , dir, &intel_host->idle_ltr); + +intel_cache_ltr (slot); +} + +static int byt_add_host (struct sdhci_pci_slot *slot) +{ +int ret =sdhci_add_host (slot->host); + +if (!ret) +byt_add_debugfs (slot); +return ret; +} + +static void byt_remove_slot (struct sdhci_pci_slot *slot,int dead) +{ +struct mmc_host *mmc = slot->host->mmc; + +if (!mmc->slotno) +intel_ltr_hide (slot->chip); }static int byt_emmc_probe_slot (struct sdhci_pci_slot *slot)
@@ -855,6 +998,8 @@ static int glk_emmc_add_host(struct sdhcif (ret) goto cleanup; +byt_add_debugfs (slot); +return 0 ; cleanup:
@@ -1032,6 +1177,8 @@ static const struct sdhci_pci_fixes sdhc#endif .allow_runtime_pm = true, .probe_slot = byt_emmc_probe_slot, + .add_host = byt_add_host, + .remove_slot = byt_remove_slot, .quirks =SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | SDHCI_QUIRK_NO_LED, .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
@@ -1045,6 +1192,7 @@ static const struct sdhci_pci_fixes sdhc .allow_runtime_pm = true, .probe_slot = glk_emmc_probe_slot, .add_host = glk_emmc_add_host, + .remove_slot = byt_remove_slot, #ifdef CONFIG_PM_SLEEP .suspend = sdhci_cqhci_suspend, .resume = sdhci_cqhci_resume,
@@ -1075,6 +1223,8 @@ static const struct sdhci_pci_fixes sdhc SDHCI_QUIRK2_PRESET_VALUE_BROKEN, .allow_runtime_pm = true, .probe_slot = ni_byt_sdio_probe_slot, + .add_host = byt_add_host, + .remove_slot = byt_remove_slot, .ops = &sdhci_intel_byt_ops, .priv_size = sizeof(struct intel_host), };
@@ -1092,6 +1242,8 @@ static const struct sdhci_pci_fixes sdhc SDHCI_QUIRK2_PRESET_VALUE_BROKEN, .allow_runtime_pm = true, .probe_slot = byt_sdio_probe_slot, + .add_host = byt_add_host, + .remove_slot = byt_remove_slot, .ops = &sdhci_intel_byt_ops, .priv_size = sizeof(struct intel_host), };
@@ -1111,6 +1263,8 @@ static const struct sdhci_pci_fixes sdhc .allow_runtime_pm = true, .own_cd_for_runtime_pm = true, .probe_slot = byt_sd_probe_slot, + .add_host = byt_add_host, + .remove_slot = byt_remove_slot, .ops = &sdhci_intel_byt_ops, .priv_size = sizeof(struct intel_host), };
Greg Kroah-Hartman
maintainerPATCH 187/391 mmc: sdhci-acpi: AMDI0040: Set SDHCI_QUIRK2_PRESET_VALUE_BROKEN
In reply to Greg Kroah-HartmanFrom: Raul E Rangel <[email protected]>
commit f23cc3ba491af77395cea3f9d51204398729f26b upstream.
This change fixes HS400 tuning for devices with invalid presets.
SDHCI presets are not currently used for eMMC HS/HS200/HS400, but are used for DDR52. The HS400 retuning sequence is:
HS400->DDR52->HS->HS200->Perform Tuning->HS->HS400
This means that when HS400 tuning happens, we transition through DDR52 for a very brief period. This causes presets to be enabled unintentionally and stay enabled when transitioning back to HS200 or HS400. Some firmware has invalid presets, so we end up with driver strengths that can cause I/O problems.
--- drivers/mmc/host/sdhci-acpi.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+)
drivers/mmc/host/sdhci-acpi.c +37 -0
@@ -662,6 +662,43 @@ static int sdhci_acpi_emmc_amd_probe_slo (host->mmc->caps & MMC_CAP_1_8V_DDR)) host->mmc->caps2 =MMC_CAP2_HS400_1_8V ; +/* +* There are two types of presets out in the wild: +* 1) Default/broken presets. +* These presets have two sets of problems: +* a) The clock divisor for SDR12, SDR25, and SDR50 is too small. +* This results in clock frequencies that are 2x higher than +* acceptable. i.e., SDR12 = 25 MHz, SDR25 = 50 MHz, SDR50 = +* 100 MHz.x +* b) The HS200 and HS400 driver strengths don't match. +* By default, the SDR104 preset register has a driver strength of +* A, but the (internal) HS400 preset register has a driver +* strength of B. As part of initializing HS400, HS200 tuning +* needs to be performed. Having different driver strengths +* between tuning and operation is wrong. It results in different +* rise/fall times that lead to incorrect sampling. +* 2) Firmware with properly initialized presets. +* These presets have proper clock divisors. i.e., SDR12 => 12MHz, +* SDR25 => 25 MHz, SDR50 => 50 MHz. Additionally the HS200 and +* HS400 preset driver strengths match. +* +* Enabling presets for HS400 doesn't work for the following reasons: +* 1) sdhci_set_ios has a hard coded list of timings that are used +* to determine if presets should be enabled. +* 2) sdhci_get_preset_value is using a non-standard register to +* read out HS400 presets. The AMD controller doesn't support this +* non-standard register. In fact, it doesn't expose the HS400 +* preset register anywhere in the SDHCI memory map. This results +* in reading a garbage value and using the wrong presets. +* +* Since HS400 and HS200 presets must be identical, we could +* instead use the the SDR104 preset register. +* +* If the above issues are resolved we could remove this quirk for +* firmware that that has valid presets (i.e., SDR12 <= 12 MHz). +*/ + host->quirks2 |=SDHCI_QUIRK2_PRESET_VALUE_BROKEN ; + host->mmc_host_ops.select_drive_strength = amd_select_drive_strength; host->mmc_host_ops.set_ios = amd_set_ios; host->mmc_host_ops.execute_tuning = amd_sdhci_execute_tuning;
Greg Kroah-Hartman
maintainerPATCH 188/391 mm: memcg/slab: uncharge during kmem_cache_free_bulk()
In reply to Greg Kroah-HartmanFrom: Bharata B Rao <[email protected]>
commit d1b2cf6cb84a9bd0de6f151512648dd1af82f80f upstream.
Object cgroup charging is done for all the objects during allocation, but during freeing, uncharging ends up happening for only one object in the case of bulk allocation/freeing.
Fix this by having a separate call to uncharge all the objects from kmem_cache_free_bulk() and by modifying memcg_slab_free_hook() to take care of bulk uncharging.
--- mm/slab.c | 2 +- mm/slab.h | 50 +++++++++++++++++++++++++++++++------------------- mm/slub.c | 3 ++- 3 files changed, 34 insertions(+), 21 deletions(-)
mm/slab.c +1 -1
@@ -3440,7 +3440,7 @@ void ___cache_free(struct kmem_cache *camemset (objp,0 , cachep->object_size);kmemleak_free_recursive (objp, cachep->flags); objp =cache_free_debugcheck (cachep, objp, caller); -memcg_slab_free_hook (cachep,virt_to_head_page (objp), objp); +memcg_slab_free_hook (cachep, &objp,1 );/* * Skip calling cache_free_alien() when the platform is not numa.
mm/slab.h +31 -19
69 lines not on this page · raw message
mm/slub.c +2 -1
@@ -3091,7 +3091,7 @@ static __always_inline void do_slab_freestruct kmem_cache_cpu *c;unsigned long tid; -memcg_slab_free_hook (s, page, head); +memcg_slab_free_hook (s, &head,1 ); redo:/* * Determine the currently cpus per cpu slab.
@@ -3253,6 +3253,7 @@ void kmem_cache_free_bulk(struct kmem_caif (WARN_ON (!size))return ; +memcg_slab_free_hook (s, p, size); do { struct detached_freelist df;
Greg Kroah-Hartman
maintainerPATCH 189/391 seccomp: Make duplicate listener detection non-racy
In reply to Greg Kroah-HartmanFrom: Jann Horn <[email protected]>
commit dfe719fef03d752f1682fa8aeddf30ba501c8555 upstream.
Currently, init_listener() tries to prevent adding a filter with SECCOMP_FILTER_FLAG_NEW_LISTENER if one of the existing filters already has a listener. However, this check happens without holding any lock that would prevent another thread from concurrently installing a new filter (potentially with a listener) on top of the ones we already have.
Theoretically, this is also a data race: The plain load from current->seccomp.filter can race with concurrent writes to the same location.
Fix it by moving the check into the region that holds the siglock to guard against concurrent TSYNC.
(The "Fixes" tag points to the commit that introduced the theoretical data race; concurrent installation of another filter with TSYNC only became possible later, in commit 51891498f2da ("seccomp: allow TSYNC and USER_NOTIF together").)
--- kernel/seccomp.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-)
kernel/seccomp.c +31 -7
@@ -1472,13 +1472,7 @@ static const struct file_operations seccstatic struct file *init_listener (struct seccomp_filter *filter) { -struct file *ret =ERR_PTR (-EBUSY ); -struct seccomp_filter *cur; - -for (cur = current->seccomp.filter; cur; cur = cur->prev) { -if (cur->notif) - goto out; - } +struct file *ret; ret =ERR_PTR (-ENOMEM ); filter->notif =kzalloc (sizeof (*(filter->notif)),GFP_KERNEL );
@@ -1504,6 +1498,31 @@ out:return ret; } +/* +* Does @new_child have a listener while an ancestor also has a listener? +* If so, we'll want to reject this filter. +* This only has to be tested for the current process, even in the TSYNC case, +* because TSYNC installs @child with the same parent on all threads. +* Note that @new_child is not hooked up to its parent at this point yet, so +* we use current->seccomp.filter. +*/ +static bool has_duplicate_listener (struct seccomp_filter *new_child) +{ +struct seccomp_filter *cur; + +/* must be protected against concurrent TSYNC */ +lockdep_assert_held (¤t->sighand->siglock); + +if (!new_child->notif) +return false; +for (cur = current->seccomp.filter; cur; cur = cur->prev) { +if (cur->notif) +return true; + } + +return false; +} +/** * seccomp_set_mode_filter: internal function for setting seccomp filter * @flags: flags to change filter behavior
@@ -1575,6 +1594,11 @@ static long seccomp_set_mode_filter(unsiif (!seccomp_may_assign_mode (seccomp_mode)) goto out; +if (has_duplicate_listener (prepared)) { + ret = -EBUSY ; + goto out; + } + ret =seccomp_attach_filter (flags, prepared);if (ret) goto out;
Greg Kroah-Hartman
maintainerPATCH 190/391 selftests/x86/fsgsbase: Test PTRACE_PEEKUSER for GSBASE with invalid LDT GS
In reply to Greg Kroah-HartmanFrom: Andy Lutomirski <[email protected]>
commit 1b9abd1755ad947d7c9913e92e7837b533124c90 upstream.
This tests commit:
8ab49526b53d ("x86/fsgsbase/64: Fix NULL deref in 86_fsgsbase_read_task")
Unpatched kernels will OOPS.
--- tools/testing/selftests/x86/fsgsbase.c | 65 +++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+)
tools/testing/selftests/x86/fsgsbase.c +65 -0
@@ -443,6 +443,68 @@ static void test_unexpected_base(void)#define USER_REGS_OFFSET (r) offsetof(struct user_regs_struct, r) +static void test_ptrace_write_gs_read_base (void ) +{ +int status; +pid_t child =fork (); + +if (child <0 ) +err (1 ,"fork" ); + +if (child ==0 ) { +printf ("[RUN]\tPTRACE_POKE GS, read GSBASE back\n" ); + +printf ("[RUN]\tARCH_SET_GS to 1\n" ); +if (syscall (SYS_arch_prctl,ARCH_SET_GS ,1 ) !=0 ) +err (1 ,"ARCH_SET_GS" ); + +if (ptrace (PTRACE_TRACEME ,0 ,NULL ,NULL ) !=0 ) +err (1 ,"PTRACE_TRACEME" ); + +raise (SIGTRAP ); +_exit (0 ); + } + +wait (&status); + +if (WSTOPSIG (status) ==SIGTRAP ) { +unsigned long base; +unsigned long gs_offset =USER_REGS_OFFSET (gs); +unsigned long base_offset =USER_REGS_OFFSET (gs_base); + +/* Read the initial base. It should be 1. */ + base =ptrace (PTRACE_PEEKUSER , child, base_offset,NULL ); +if (base ==1 ) { +printf ("[OK]\tGSBASE started at 1\n" ); + }else { + nerrs++; +printf ("[FAIL]\tGSBASE started at 0x%lx\n" , base); + } + +printf ("[RUN]\tSet GS = 0x7, read GSBASE\n" ); + +/* Poke an LDT selector into GS. */ +if (ptrace (PTRACE_POKEUSER , child, gs_offset,0x7 ) !=0 ) +err (1 ,"PTRACE_POKEUSER" ); + +/* And read the base. */ + base =ptrace (PTRACE_PEEKUSER , child, base_offset,NULL ); + +if (base ==0 || base ==1 ) { +printf ("[OK]\tGSBASE reads as 0x%lx with invalid GS\n" , base); + }else { + nerrs++; +printf ("[FAIL]\tGSBASE=0x%lx (should be 0 or 1)\n" , base); + } + } + +ptrace (PTRACE_CONT , child,NULL ,NULL ); + +wait (&status); +if (!WIFEXITED (status)) +printf ("[WARN]\tChild didn't exit cleanly.\n" ); +} +static void test_ptrace_write_gsbase (void ) {int status;
@@ -529,6 +591,9 @@ int main() shared_scratch =mmap (NULL ,4096 ,PROT_READ |PROT_WRITE ,MAP_ANONYMOUS |MAP_SHARED ,-1 ,0 ); +/* Do these tests before we have an LDT. */ +test_ptrace_write_gs_read_base (); +/* Probe FSGSBASE */ sethandler (SIGILL , sigill,0 );if (sigsetjmp (jmpbuf,1 ) ==0 ) {
Greg Kroah-Hartman
maintainerPATCH 191/391 perf/x86/intel: Fix Ice Lake event constraint table
In reply to Greg Kroah-HartmanFrom: Kan Liang <[email protected]>
commit 010cb00265f150bf82b23c02ad1fb87ce5c781e1 upstream.
An error occues when sampling non-PEBS INST_RETIRED.PREC_DIST(0x01c0) event.
perf record -e cpu/event=0xc0,umask=0x01/ -- sleep 1 Error:
The sys_perf_event_open() syscall returned with 22 (Invalid argument) for event (cpu/event=0xc0,umask=0x01/).
/bin/dmesg | grep -i perf may provide additional information.
The idxmsk64 of the event is set to 0. The event never be successfully scheduled.
The event should be limit to the fixed counter 0.
--- arch/x86/events/intel/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/events/intel/core.c +1 -1
@@ -243,7 +243,7 @@ static struct extra_reg intel_skl_extra_static struct event_constraint intel_icl_event_constraints[] = {FIXED_EVENT_CONSTRAINT (0x00c0 ,0 ),/* INST_RETIRED.ANY */ -INTEL_UEVENT_CONSTRAINT (0x1c0 ,0 ),/* INST_RETIRED.PREC_DIST */ +FIXED_EVENT_CONSTRAINT (0x01c0 ,0 ),/* INST_RETIRED.PREC_DIST */ FIXED_EVENT_CONSTRAINT (0x003c ,1 ),/* CPU_CLK_UNHALTED.CORE */ FIXED_EVENT_CONSTRAINT (0x0300 ,2 ),/* CPU_CLK_UNHALTED.REF */ FIXED_EVENT_CONSTRAINT (0x0400 ,3 ),/* SLOTS */
Greg Kroah-Hartman
maintainerPATCH 192/391 perf/x86/amd: Fix sampling Large Increment per Cycle events
In reply to Greg Kroah-HartmanFrom: Kim Phillips <[email protected]>
commit 26e52558ead4b39c0e0fe7bf08f82f5a9777a412 upstream.
Commit 5738891229a2 ("perf/x86/amd: Add support for Large Increment per Cycle Events") mistakenly zeroes the upper 16 bits of the count in set_period(). That's fine for counting with perf stat, but not sampling with perf record when only Large Increment events are being sampled. To enable sampling, we sign extend the upper 16 bits of the merged counter pair as described in the Family 17h PPRs:
"Software wanting to preload a value to a merged counter pair writes the high-order 16-bit value to the low-order 16 bits of the odd counter and then writes the low-order 48-bit value to the even counter. Reading the even counter of the merged counter pair returns the full 64-bit value."
--- arch/x86/events/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/events/core.c +2 -2
@@ -1286,11 +1286,11 @@ int x86_perf_event_set_period(struct perwrmsrl (hwc->event_base, (u64)(-left) & x86_pmu.cntval_mask);/* -* Clear the Merge event counter's upper 16 bits since +* Sign extend the Merge event counter's upper 16 bits since * we currently declare a 48-bit counter width */ if (is_counter_pair (hwc)) -wrmsrl (x86_pmu_event_addr (idx +1 ),0 ); +wrmsrl (x86_pmu_event_addr (idx +1 ),0xffff );/* * Due to erratum on certan cpu we need
Greg Kroah-Hartman
maintainerPATCH 193/391 perf/amd/uncore: Set all slices and threads to restore perf stat -a behaviour
In reply to Greg Kroah-HartmanFrom: Kim Phillips <[email protected]>
commit c8fe99d0701fec9fb849ec880a86bc5592530496 upstream.
Commit 2f217d58a8a0 ("perf/x86/amd/uncore: Set the thread mask for F17h L3 PMCs") inadvertently changed the uncore driver's behaviour wrt perf tool invocations with or without a CPU list, specified with -C / --cpu=.
Change the behaviour of the driver to assume the former all-cpu (-a) case, which is the more commonly desired default. This fixes '-a -A' invocations without explicit cpu lists (-C) to not count L3 events only on behalf of the first thread of the first core in the L3 domain.
BEFORE:
Activity performed by the first thread of the last core (CPU#43) in CPU#40's L3 domain is not reported by CPU#40:
sudo perf stat -a -A -e l3_request_g1.caching_l3_cache_accesses taskset -c 43 perf bench mem memcpy -s 32mb -l 100 -f default
...
CPU36 21,835 l3_request_g1.caching_l3_cache_accesses CPU40 87,066 l3_request_g1.caching_l3_cache_accesses CPU44 17,360 l3_request_g1.caching_l3_cache_accesses
...
AFTER:
The L3 domain activity is now reported by CPU#40:
sudo perf stat -a -A -e l3_request_g1.caching_l3_cache_accesses taskset -c 43 perf bench mem memcpy -s 32mb -l 100 -f default
...
CPU36 354,891 l3_request_g1.caching_l3_cache_accesses CPU40 1,780,870 l3_request_g1.caching_l3_cache_accesses CPU44 315,062 l3_request_g1.caching_l3_cache_accesses
...
--- arch/x86/events/amd/uncore.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-)
arch/x86/events/amd/uncore.c +8 -20
@@ -181,28 +181,16 @@ static void amd_uncore_del(struct perf_e }/* -* Convert logical CPU number to L3 PMC Config ThreadMask format +* Return a full thread and slice mask until per-CPU is +* properly supported. */ -static u64 l3_thread_slice_mask (int cpu) +static u64 l3_thread_slice_mask (void ) { -u64 thread_mask, core =topology_core_id (cpu); -unsigned int shift, thread =0 ; +if (boot_cpu_data.x86 <=0x18 ) +return AMD64_L3_SLICE_MASK |AMD64_L3_THREAD_MASK ; -if (topology_smt_supported () && !topology_is_primary_thread (cpu)) - thread =1 ; - -if (boot_cpu_data.x86 <=0x18 ) { - shift =AMD64_L3_THREAD_SHIFT +2 * (core %4 ) + thread; - thread_mask =BIT_ULL (shift); - -return AMD64_L3_SLICE_MASK | thread_mask; - } - - core = (core <<AMD64_L3_COREID_SHIFT ) &AMD64_L3_COREID_MASK ; - shift =AMD64_L3_THREAD_SHIFT + thread; - thread_mask =BIT_ULL (shift); - -return AMD64_L3_EN_ALL_SLICES | core | thread_mask; +return AMD64_L3_EN_ALL_SLICES |AMD64_L3_EN_ALL_CORES | +AMD64_L3_F19H_THREAD_MASK ; }static int amd_uncore_event_init (struct perf_event *event)
@@ -232,7 +220,7 @@ static int amd_uncore_event_init(struct* For other events, the two fields do not affect the count. */ if (l3_mask &&is_llc_event (event)) - hwc->config |=l3_thread_slice_mask (event->cpu); + hwc->config |=l3_thread_slice_mask (); uncore =event_to_amd_uncore (event);if (!uncore)
Greg Kroah-Hartman
maintainerPATCH 194/391 perf/x86/amd/ibs: Dont include randomized bits in get_ibs_op_count()
In reply to Greg Kroah-HartmanFrom: Kim Phillips <[email protected]>
commit 680d69635005ba0e58fe3f4c52fc162b8fc743b0 upstream.
get_ibs_op_count() adds hardware's current count (IbsOpCurCnt) bits to its count regardless of hardware's valid status.
According to the PPR for AMD Family 17h Model 31h B0 55803 Rev 0.54, if the counter rolls over, valid status is set, and the lower 7 bits of IbsOpCurCnt are randomized by hardware.
Don't include those bits in the driver's event count.
--- arch/x86/events/amd/ibs.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
arch/x86/events/amd/ibs.c +8 -4
@@ -335,11 +335,15 @@ static u64 get_ibs_op_count(u64 config) {u64 count =0 ; +/* +* If the internal 27-bit counter rolled over, the count is MaxCnt +* and the lower 7 bits of CurCnt are randomized. +* Otherwise CurCnt has the full 27-bit current counter value. +*/ if (config &IBS_OP_VAL ) - count += (config &IBS_OP_MAX_CNT ) <<4 ;/* cnt rolled over */ - -if (ibs_caps &IBS_CAPS_RDWROPCNT ) - count += (config &IBS_OP_CUR_CNT ) >>32 ; + count = (config &IBS_OP_MAX_CNT ) <<4 ; +else if (ibs_caps &IBS_CAPS_RDWROPCNT ) + count = (config &IBS_OP_CUR_CNT ) >>32 ;return count; }
Greg Kroah-Hartman
maintainerPATCH 195/391 perf/x86/amd/ibs: Fix raw sample data accumulation
In reply to Greg Kroah-HartmanFrom: Kim Phillips <[email protected]>
commit 36e1be8ada994d509538b3b1d0af8b63c351e729 upstream.
Neither IbsBrTarget nor OPDATA4 are populated in IBS Fetch mode. Don't accumulate them into raw sample user data in that case.
Also, in Fetch mode, add saving the IBS Fetch Control Extended MSR.
Technically, there is an ABI change here with respect to the IBS raw sample data format, but I don't see any perf driver version information being included in perf.data file headers, but, existing users can detect whether the size of the sample record has reduced by 8 bytes to determine whether the IBS driver has this fix.
--- arch/x86/events/amd/ibs.c | 26 ++++++++++++++++---------- arch/x86/include/asm/msr-index.h | 1 + 2 files changed, 17 insertions(+), 10 deletions(-)
arch/x86/events/amd/ibs.c +16 -10
@@ -636,18 +636,24 @@ fail: perf_ibs->offset_max, offset + 1); }while (offset < offset_max); +/* +* Read IbsBrTarget, IbsOpData4, and IbsExtdCtl separately +* depending on their availability. +* Can't add to offset_max as they are staggered +*/ if (event->attr.sample_type &PERF_SAMPLE_RAW ) { -/* -* Read IbsBrTarget and IbsOpData4 separately -* depending on their availability. -* Can't add to offset_max as they are staggered -*/ -if (ibs_caps &IBS_CAPS_BRNTRGT ) { -rdmsrl (MSR_AMD64_IBSBRTARGET , *buf++); - size++; +if (perf_ibs == &perf_ibs_op) { +if (ibs_caps &IBS_CAPS_BRNTRGT ) { +rdmsrl (MSR_AMD64_IBSBRTARGET , *buf++); + size++; + } +if (ibs_caps &IBS_CAPS_OPDATA4 ) { +rdmsrl (MSR_AMD64_IBSOPDATA4 , *buf++); + size++; + } } -if (ibs_caps &IBS_CAPS_OPDATA4 ) { -rdmsrl (MSR_AMD64_IBSOPDATA4 , *buf++); +if (perf_ibs == &perf_ibs_fetch && (ibs_caps &IBS_CAPS_FETCHCTLEXTD )) { +rdmsrl (MSR_AMD64_ICIBSEXTDCTL , *buf++); size++; } }
arch/x86/include/asm/msr-index.h +1 -0
@@ -464,6 +464,7 @@#define MSR_AMD64_IBSOP_REG_MASK ((1UL<<MSR_AMD64_IBSOP_REG_COUNT)-1)#define MSR_AMD64_IBSCTL 0xc001103a#define MSR_AMD64_IBSBRTARGET 0xc001103b +#define MSR_AMD64_ICIBSEXTDCTL 0xc001103c#define MSR_AMD64_IBSOPDATA4 0xc001103d#define MSR_AMD64_IBS_REG_COUNT_MAX 8/* includes MSR_AMD64_IBSBRTARGET */ #define MSR_AMD64_SEV 0xc0010131
Greg Kroah-Hartman
maintainerPATCH 196/391 spi: spi-mtk-nor: fix timeout calculation overflow
In reply to Greg Kroah-HartmanFrom: Chuanhong Guo <[email protected]>
commit 4cafaddedb5fbef9531202ee547784409fd0de33 upstream.
CLK_TO_US macro is used to calculate potential transfer time for various timeout handling. However it overflows on transfer bigger than 512 bytes because it first did (len * 8 * 1000000).
This controller typically operates at 45MHz. This patch did 2 things:
1. calculate clock / 1000000 first
2. add a 4M transfer size cap so that the final timeout in DMA reading doesn't overflow
--- drivers/spi/spi-mtk-nor.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/spi/spi-mtk-nor.c +5 -1
@@ -89,7 +89,7 @@// Buffered page program can do one 128-byte transfer #define MTK_NOR_PP_SIZE 128 -#define CLK_TO_US (sp, clkcnt) ((clkcnt) * 1000000 / sp->spi_freq) +#define CLK_TO_US (sp, clkcnt) DIV_ROUND_UP(clkcnt, sp->spi_freq / 1000000)struct mtk_nor {struct spi_controller *ctlr;
@@ -177,6 +177,10 @@ static int mtk_nor_adjust_op_size(structif ((op->addr.nbytes ==3 ) || (op->addr.nbytes ==4 )) {if ((op->data.dir ==SPI_MEM_DATA_IN ) &&mtk_nor_match_read (op)) { +// limit size to prevent timeout calculation overflow +if (op->data.nbytes >0x400000 ) + op->data.nbytes =0x400000 ; +if ((op->addr.val &MTK_NOR_DMA_ALIGN_MASK ) || (op->data.nbytes <MTK_NOR_DMA_ALIGN )) op->data.nbytes =1 ;
Greg Kroah-Hartman
maintainerPATCH 197/391 spi: sprd: Release DMA channel also on probe deferral
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
commit 687a2e76186dcfa42f22c14b655c3fb159839e79 upstream.
If dma_request_chan() for TX channel fails with EPROBE_DEFER, the RX channel would not be released and on next re-probe it would be requested second time.
--- drivers/spi/spi-sprd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/spi/spi-sprd.c +1 -1
@@ -563,11 +563,11 @@ static int sprd_spi_dma_request(struct s ss->dma.dma_chan[SPRD_SPI_TX ] =dma_request_chan (ss->dev,"tx_chn" );if (IS_ERR_OR_NULL (ss->dma.dma_chan[SPRD_SPI_TX ])) { +dma_release_channel (ss->dma.dma_chan[SPRD_SPI_RX ]);if (PTR_ERR (ss->dma.dma_chan[SPRD_SPI_TX ]) == -EPROBE_DEFER )return PTR_ERR (ss->dma.dma_chan[SPRD_SPI_TX ]);dev_err (ss->dev,"request TX DMA channel failed!\n" ); -dma_release_channel (ss->dma.dma_chan[SPRD_SPI_RX ]);return PTR_ERR (ss->dma.dma_chan[SPRD_SPI_TX ]); }
Greg Kroah-Hartman
maintainerPATCH 198/391 extcon: ptn5150: Fix usage of atomic GPIO with sleeping GPIO chips
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
commit 6aaad58c872db062f7ea2761421ca748bd0931cc upstream.
The driver uses atomic version of gpiod_set_value() without any real reason. It is called in a workqueue under mutex so it could sleep there. Changing it to "can_sleep" flavor allows to use the driver with all GPIO chips.
--- drivers/extcon/extcon-ptn5150.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/extcon/extcon-ptn5150.c +4 -4
@@ -127,7 +127,7 @@ static void ptn5150_irq_work(struct workcase PTN5150_DFP_ATTACHED :extcon_set_state_sync (info->edev,EXTCON_USB_HOST , false); -gpiod_set_value (info->vbus_gpiod,0 ); +gpiod_set_value_cansleep (info->vbus_gpiod,0 );extcon_set_state_sync (info->edev,EXTCON_USB , true);break ;
@@ -138,9 +138,9 @@ static void ptn5150_irq_work(struct work PTN5150_REG_CC_VBUS_DETECTION_MASK) >> PTN5150_REG_CC_VBUS_DETECTION_SHIFT);if (vbus) -gpiod_set_value (info->vbus_gpiod,0 ); +gpiod_set_value_cansleep (info->vbus_gpiod,0 );else -gpiod_set_value (info->vbus_gpiod,1 ); +gpiod_set_value_cansleep (info->vbus_gpiod,1 );extcon_set_state_sync (info->edev,EXTCON_USB_HOST , true);
@@ -156,7 +156,7 @@ static void ptn5150_irq_work(struct work EXTCON_USB_HOST, false);extcon_set_state_sync (info->edev,EXTCON_USB , false); -gpiod_set_value (info->vbus_gpiod,0 ); +gpiod_set_value_cansleep (info->vbus_gpiod,0 ); } }
Greg Kroah-Hartman
maintainerPATCH 199/391 leds: bcm6328, bcm6358: use devres LED registering function
In reply to Greg Kroah-HartmanFrom: Marek Behún <[email protected]>
commit ff5c89d44453e7ad99502b04bf798a3fc32c758b upstream.
These two drivers do not provide remove method and use devres for allocation of other resources, yet they use led_classdev_register instead of the devres variant, devm_led_classdev_register.
Fix this.
--- drivers/leds/leds-bcm6328.c | 2 +- drivers/leds/leds-bcm6358.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/leds/leds-bcm6328.c +1 -1
@@ -383,7 +383,7 @@ static int bcm6328_led(struct device *de led->cdev.brightness_set = bcm6328_led_set; led->cdev.blink_set = bcm6328_blink_set; - rc =led_classdev_register (dev, &led->cdev); + rc =devm_led_classdev_register (dev, &led->cdev);if (rc <0 )return rc;
drivers/leds/leds-bcm6358.c +1 -1
@@ -137,7 +137,7 @@ static int bcm6358_led(struct device *de led->cdev.brightness_set = bcm6358_led_set; - rc =led_classdev_register (dev, &led->cdev); + rc =devm_led_classdev_register (dev, &led->cdev);if (rc <0 )return rc;
Greg Kroah-Hartman
maintainerPATCH 200/391 hwmon: (pmbus/max34440) Fix OC fault limits
In reply to Greg Kroah-HartmanFrom: Steve Foreman <[email protected]>
commit 2b52278150c49559a472f2d6dd66f6f3b405378e upstream.
The max34* family have the IOUT_OC_WARN_LIMIT and IOUT_OC_CRIT_LIMIT registers swapped.
--- drivers/hwmon/pmbus/max34440.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
drivers/hwmon/pmbus/max34440.c +23 -0
@@ -31,6 +31,13 @@ enum chips { max34440, max34441, max3444#define MAX34440_STATUS_OT_FAULT BIT(5)#define MAX34440_STATUS_OT_WARN BIT(6) +/* +* The whole max344* family have IOUT_OC_WARN_LIMIT and IOUT_OC_FAULT_LIMIT +* swapped from the standard pmbus spec addresses. +*/ +#define MAX34440_IOUT_OC_WARN_LIMIT 0x46 +#define MAX34440_IOUT_OC_FAULT_LIMIT 0x4A +#define MAX34451_MFR_CHANNEL_CONFIG 0xe4#define MAX34451_MFR_CHANNEL_CONFIG_SEL_MASK 0x3f
@@ -49,6 +56,14 @@ static int max34440_read_word_data(strucconst struct max34440_data *data =to_max34440_data (info);switch (reg) { +case PMBUS_IOUT_OC_FAULT_LIMIT : + ret =pmbus_read_word_data (client, page, phase, +MAX34440_IOUT_OC_FAULT_LIMIT ); +break ; +case PMBUS_IOUT_OC_WARN_LIMIT : + ret =pmbus_read_word_data (client, page, phase, +MAX34440_IOUT_OC_WARN_LIMIT ); +break ;case PMBUS_VIRT_READ_VOUT_MIN : ret =pmbus_read_word_data (client, page, phase,MAX34440_MFR_VOUT_MIN );
@@ -115,6 +130,14 @@ static int max34440_write_word_data(struint ret;switch (reg) { +case PMBUS_IOUT_OC_FAULT_LIMIT : + ret =pmbus_write_word_data (client, page,MAX34440_IOUT_OC_FAULT_LIMIT , + word); +break ; +case PMBUS_IOUT_OC_WARN_LIMIT : + ret =pmbus_write_word_data (client, page,MAX34440_IOUT_OC_WARN_LIMIT , + word); +break ;case PMBUS_VIRT_RESET_POUT_HISTORY : ret =pmbus_write_word_data (client, page,MAX34446_MFR_POUT_PEAK ,0 );
Greg Kroah-Hartman
maintainerPATCH 201/391 media: uvcvideo: Fix uvc_ctrl_fixup_xu_info() not having any effect
In reply to Greg Kroah-HartmanFrom: Hans de Goede <[email protected]>
commit 93df48d37c3f03886d84831992926333e7810640 upstream.
uvc_ctrl_add_info() calls uvc_ctrl_get_flags() which will override the fixed-up flags set by uvc_ctrl_fixup_xu_info().
uvc_ctrl_init_xu_ctrl() already calls uvc_ctrl_get_flags() before calling uvc_ctrl_add_info(), so the uvc_ctrl_get_flags() call in uvc_ctrl_add_info() is not necessary for xu ctrls.
This commit moves the uvc_ctrl_get_flags() call for normal controls from uvc_ctrl_add_info() to uvc_ctrl_init_ctrl(), so that we no longer call uvc_ctrl_get_flags() twice for xu controls and so that we no longer override the fixed-up flags set by uvc_ctrl_fixup_xu_info().
This fixes the xu motor controls not working properly on a Logitech 046d:08cc, and presumably also on the other Logitech models which have a quirk for this in the uvc_ctrl_fixup_xu_info() function.
--- drivers/media/usb/uvc/uvc_ctrl.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/media/usb/uvc/uvc_ctrl.c +7 -7
@@ -2033,13 +2033,6 @@ static int uvc_ctrl_add_info(struct uvc_ goto done; } -/* -* Retrieve control flags from the device. Ignore errors and work with -* default flag values from the uvc_ctrl array when the device doesn't -* properly implement GET_INFO on standard controls. -*/ -uvc_ctrl_get_flags (dev, ctrl, &ctrl->info); - ctrl->initialized =1 ; uvc_trace(UVC_TRACE_CONTROL, "Added control %pUl/%u to device %s "
@@ -2262,6 +2255,13 @@ static void uvc_ctrl_init_ctrl(struct uvif (uvc_entity_match_guid (ctrl->entity, info->entity) && ctrl->index == info->index) {uvc_ctrl_add_info (dev, ctrl, info); +/* +* Retrieve control flags from the device. Ignore errors +* and work with default flag values from the uvc_ctrl +* array when the device doesn't properly implement +* GET_INFO on standard controls. +*/ +uvc_ctrl_get_flags (dev, ctrl, &ctrl->info);break ; } }
Greg Kroah-Hartman
maintainerPATCH 202/391 fs: Dont invalidate page buffers in block_write_full_page()
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
commit 6dbf7bb555981fb5faf7b691e8f6169fc2b2e63b upstream.
If block_write_full_page() is called for a page that is beyond current inode size, it will truncate page buffers for the page and return 0. This logic has been added in 2.5.62 in commit 81eb69062588 ("fix ext3 BUG due to race with truncate") in history.git tree to fix a problem with ext3 in data=ordered mode. This particular problem doesn't exist anymore because ext3 is long gone and ext4 handles ordered data differently. Also normally buffers are invalidated by truncate code and there's no need to specially handle this in ->writepage() code.
This invalidation of page buffers in block_write_full_page() is causing issues to filesystems (e.g. ext4 or ocfs2) when block device is shrunk under filesystem's hands and metadata buffers get discarded while being tracked by the journalling layer. Although it is obviously "not supported" it can cause kernel crashes like:
[ 7986.689400] BUG: unable to handle kernel NULL pointer dereference at +0000000000000008 [ 7986.697197] PGD 0 P4D 0 [ 7986.699724] Oops: 0002 [#1] SMP PTI [ 7986.703200] CPU: 4 PID: 203778 Comm: jbd2/dm-3-8 Kdump: loaded Tainted: G +O --------- - - 4.18.0-147.5.0.5.h126.eulerosv2r9.x86_64 #1 [ 7986.716438] Hardware name: Huawei RH2288H V3/BC11HGSA0, BIOS 1.57 08/11/2015 [ 7986.723462] RIP: 0010:jbd2_journal_grab_journal_head+0x1b/0x40 [jbd2] ... [ 7986.810150] Call Trace: [ 7986.812595] __jbd2_journal_insert_checkpoint+0x23/0x70 [jbd2] [ 7986.818408] jbd2_journal_commit_transaction+0x155f/0x1b60 [jbd2] [ 7986.836467] kjournald2+0xbd/0x270 [jbd2]
which is not great. The crash happens because bh->b_private is suddently NULL although BH_JBD flag is still set (this is because block_invalidatepage() cleared BH_Mapped flag and subsequent bh lookup found buffer without BH_Mapped set, called init_page_buffers() which has rewritten bh->b_private). So just remove the invalidation in block_write_full_page().
Note that the buffer cache invalidation when block device changes size is already careful to avoid similar problems by using invalidate_mapping_pages() which skips busy buffers so it was only this odd block_write_full_page() behavior that could tear down bdev buffers under filesystem's hands.
--- fs/buffer.c | 16 ---------------- 1 file changed, 16 deletions(-)
fs/buffer.c +0 -16
@@ -2771,16 +2771,6 @@ int nobh_writepage(struct page *page, ge/* Is the page fully outside i_size? (truncate in progress) */ offset = i_size & (PAGE_SIZE -1 );if (page->index >= end_index+1 || !offset) { -/* -* The page may have dirty, unmapped buffers. For example, -* they may have been added in ext3_writepage(). Make them -* freeable here, so the page does not leak. -*/ -#if 0 -/* Not really sure about this - do we need this ? */ -if (page->mapping->a_ops->invalidatepage) - page->mapping->a_ops->invalidatepage (page, offset); -#endif unlock_page (page);return 0 ;/* don't care */ }
@@ -2975,12 +2965,6 @@ int block_write_full_page(struct page *p/* Is the page fully outside i_size? (truncate in progress) */ offset = i_size & (PAGE_SIZE -1 );if (page->index >= end_index+1 || !offset) { -/* -* The page may have dirty, unmapped buffers. For example, -* they may have been added in ext3_writepage(). Make them -* freeable here, so the page does not leak. -*/ -do_invalidatepage (page,0 ,PAGE_SIZE );unlock_page (page);return 0 ;/* don't care */ }
Greg Kroah-Hartman
maintainerPATCH 203/391 ACPI: configfs: Add missing config_item_put() to fix refcount leak
In reply to Greg Kroah-HartmanFrom: Hanjun Guo <[email protected]>
commit 9a2e849fb6de471b82d19989a7944d3b7671793c upstream.
config_item_put() should be called in the drop_item callback, to decrement refcount for the config item.
--- drivers/acpi/acpi_configfs.c | 1 + 1 file changed, 1 insertion(+)
drivers/acpi/acpi_configfs.c +1 -0
@@ -228,6 +228,7 @@ static void acpi_table_drop_item(structACPI_INFO (("Host-directed Dynamic ACPI Table Unload" ));acpi_unload_table (table->index); +config_item_put (cfg); }static struct configfs_group_operations acpi_table_group_ops = {
Greg Kroah-Hartman
maintainerPATCH 204/391 NFS: fix nfs_path in case of a rename retry
In reply to Greg Kroah-HartmanFrom: Ashish Sangwan <[email protected]>
commit 247db73560bc3e5aef6db50c443c3c0db115bc93 upstream.
We are generating incorrect path in case of rename retry because we are restarting from wrong dentry. We should restart from the dentry which was received in the call to nfs_path.
--- fs/nfs/namespace.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
fs/nfs/namespace.c +8 -4
@@ -32,9 +32,9 @@ int nfs_mountpoint_expiry_timeout = 500/* * nfs_path - reconstruct the path given an arbitrary dentry * @base - used to return pointer to the end of devname part of path -* @dentry - pointer to dentry +* @dentry_in - pointer to dentry * @buffer - result buffer -* @buflen - length of buffer +* @buflen_in - length of buffer * @flags - options (see below) * * Helper function for constructing the server pathname
@@ -49,15 +49,19 @@ int nfs_mountpoint_expiry_timeout = 500* the original device (export) name * (if unset, the original name is returned verbatim) */ -char *nfs_path (char **p,struct dentry *dentry,char *buffer,ssize_t buflen, -unsigned flags) +char *nfs_path (char **p,struct dentry *dentry_in,char *buffer, +ssize_t buflen_in,unsigned flags) {char *end;int namelen;unsigned seq;const char *base; +struct dentry *dentry; +ssize_t buflen; rename_retry: + buflen = buflen_in; + dentry = dentry_in; end = buffer+buflen; *--end ='\0' ; buflen--;
Greg Kroah-Hartman
maintainerPATCH 205/391 ACPI: button: fix handling lid state changes when input device closed
In reply to Greg Kroah-HartmanFrom: [email protected] <[email protected]>
commit 21988a8e51479ceffe7b0568b170effabb708dfe upstream.
The original intent of 84d3f6b76447 was to delay evaluating lid state until all drivers have been loaded, with input device being opened from userspace serving as a signal for this condition. Let's ensure that state updates happen even if userspace closed (or in the future inhibited) input device.
Note that if we go through suspend/resume cycle we assume the system has been fully initialized even if LID input device has not been opened yet.
This has a side-effect of fixing access to input->users outside of input->mutex protections by the way of eliminating said accesses and using driver private flag.
--- drivers/acpi/button.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/acpi/button.c +7 -6
@@ -153,6 +153,7 @@ struct acpi_button {int last_state;ktime_t last_time;bool suspended; +bool lid_state_initialized; };static struct acpi_device *lid_device;
@@ -383,6 +384,8 @@ static int acpi_lid_update_state(structstatic void acpi_lid_initialize_state (struct acpi_device *device) { +struct acpi_button *button =acpi_driver_data (device); +switch (lid_init_state) {case ACPI_BUTTON_LID_INIT_OPEN : (void )acpi_lid_notify_state (device,1 );
@@ -394,13 +397,14 @@ static void acpi_lid_initialize_state(stdefault :break ; } + + button->lid_state_initialized = true; }static void acpi_button_notify (struct acpi_device *device,u32 event) {struct acpi_button *button =acpi_driver_data (device);struct input_dev *input; -int users;switch (event) {case ACPI_FIXED_HARDWARE_EVENT :
@@ -409,10 +413,7 @@ static void acpi_button_notify(struct accase ACPI_BUTTON_NOTIFY_STATUS : input = button->input;if (button->type ==ACPI_BUTTON_TYPE_LID ) { -mutex_lock (&button->input->mutex); - users = button->input->users; -mutex_unlock (&button->input->mutex); -if (users) +if (button->lid_state_initialized)acpi_lid_update_state (device, true); }else {int keycode;
@@ -457,7 +458,7 @@ static int acpi_button_resume(struct devstruct acpi_button *button =acpi_driver_data (device); button->suspended = false; -if (button->type ==ACPI_BUTTON_TYPE_LID && button->input->users) { +if (button->type ==ACPI_BUTTON_TYPE_LID ) { button->last_state = !!acpi_lid_evaluate_state (device); button->last_time =ktime_get ();acpi_lid_initialize_state (device);
Greg Kroah-Hartman
maintainerPATCH 206/391 ACPI / extlog: Check for RDMSR failure
In reply to Greg Kroah-HartmanFrom: Ben Hutchings <[email protected]>
commit 7cecb47f55e00282f972a1e0b09136c8cd938221 upstream.
extlog_init() uses rdmsrl() to read an MSR, which on older CPUs provokes a error message at boot:
unchecked MSR access error: RDMSR from 0x179 at rIP: 0xcd047307 (native_read_msr+0x7/0x40)
Use rdmsrl_safe() instead, and return -ENODEV if it fails.
--- drivers/acpi/acpi_extlog.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/acpi/acpi_extlog.c +3 -3
@@ -222,9 +222,9 @@ static int __init extlog_init(void)u64 cap;int rc; -rdmsrl (MSR_IA32_MCG_CAP , cap); - -if (!(cap &MCG_ELOG_P ) || !extlog_get_l1addr ()) +if (rdmsrl_safe (MSR_IA32_MCG_CAP , &cap) || + !(cap &MCG_ELOG_P ) || + !extlog_get_l1addr ())return -ENODEV ; rc = -EINVAL ;
Greg Kroah-Hartman
maintainerPATCH 207/391 ACPI: video: use ACPI backlight for HP 635 Notebook
In reply to Greg Kroah-HartmanFrom: Alex Hung <[email protected]>
commit b226faab4e7890bbbccdf794e8b94276414f9058 upstream.
The default backlight interface is AMD's radeon_bl0 which does not work on this system, so use the ACPI backlight interface on it instead.
--- drivers/acpi/video_detect.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/acpi/video_detect.c +9 -0
@@ -282,6 +282,15 @@ static const struct dmi_system_id video_ DMI_MATCH(DMI_PRODUCT_NAME, "530U4E/540U4E"), }, }, +/* https://bugs.launchpad.net/bugs/1894667 */ + { + .callback = video_detect_force_video, + .ident = "HP 635 Notebook", + .matches = { +DMI_MATCH (DMI_SYS_VENDOR ,"Hewlett-Packard" ), + DMI_MATCH(DMI_PRODUCT_NAME, "HP 635 Notebook PC"), + }, + }, /* Non win8 machines which need native backlight nevertheless */ {
Greg Kroah-Hartman
maintainerPATCH 208/391 ACPI: debug: dont allow debugging when ACPI is disabled
In reply to Greg Kroah-HartmanFrom: Jamie Iles <[email protected]>
commit 0fada277147ffc6d694aa32162f51198d4f10d94 upstream.
If ACPI is disabled then loading the acpi_dbg module will result in the following splat when lock debugging is enabled.
DEBUG_LOCKS_WARN_ON(lock->magic != lock)
WARNING: CPU: 0 PID: 1 at kernel/locking/mutex.c:938 __mutex_lock+0xa10/0x1290 Kernel panic - not syncing: panic_on_warn set ... CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.9.0-rc8+ #103 Hardware name: linux,dummy-virt (DT) Call trace: dump_backtrace+0x0/0x4d8 show_stack+0x34/0x48 dump_stack+0x174/0x1f8 panic+0x360/0x7a0 __warn+0x244/0x2ec report_bug+0x240/0x398 bug_handler+0x50/0xc0 call_break_hook+0x160/0x1d8 brk_handler+0x30/0xc0 do_debug_exception+0x184/0x340 el1_dbg+0x48/0xb0 el1_sync_handler+0x170/0x1c8 el1_sync+0x80/0x100 __mutex_lock+0xa10/0x1290 mutex_lock_nested+0x6c/0xc0 acpi_register_debugger+0x40/0x88 acpi_aml_init+0xc4/0x114 do_one_initcall+0x24c/0xb10 kernel_init_freeable+0x690/0x728 kernel_init+0x20/0x1e8 ret_from_fork+0x10/0x18
This is because acpi_debugger.lock has not been initialized as acpi_debugger_init() is not called when ACPI is disabled. Fail module loading to avoid this and any subsequent problems that might arise by trying to debug AML when ACPI is disabled.
--- drivers/acpi/acpi_dbg.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/acpi/acpi_dbg.c +3 -0
@@ -749,6 +749,9 @@ static int __init acpi_aml_init(void) {int ret; +if (acpi_disabled) +return -ENODEV ; +/* Initialize AML IO interface */ mutex_init (&acpi_aml_io.lock);init_waitqueue_head (&acpi_aml_io.wait);
Greg Kroah-Hartman
maintainerPATCH 209/391 PCI/ACPI: Whitelist hotplug ports for D3 if power managed by ACPI
In reply to Greg Kroah-HartmanFrom: Lukas Wunner <[email protected]>
commit c6e331312ebfb52b7186e5d82d517d68b4d2f2d8 upstream.
Recent laptops with dual AMD GPUs fail to suspend the discrete GPU, thus causing lockups on system sleep and high power consumption at runtime. The discrete GPU would normally be suspended to D3cold by turning off ACPI _PR3 Power Resources of the Root Port above the GPU.
However on affected systems, the Root Port is hotplug-capable and pci_bridge_d3_possible() only allows hotplug ports to go to D3 if they belong to a Thunderbolt device or if the Root Port possesses a "HotPlugSupportInD3" ACPI property. Neither is the case on affected laptops. The reason for whitelisting only specific, known to work hotplug ports for D3 is that there have been reports of SkyLake Xeon-SP systems raising Hardware Error NMIs upon suspending their hotplug ports:
https://lore.kernel.org/linux-pci/20170503180426.GA4058@otc-nc-03/
But if a hotplug port is power manageable by ACPI (as can be detected through presence of Power Resources and corresponding _PS0 and _PS3 methods) then it ought to be safe to suspend it to D3. To this end, amend acpi_pci_bridge_d3() to whitelist such ports for D3.
--- drivers/pci/pci-acpi.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
drivers/pci/pci-acpi.c +10 -0
@@ -944,6 +944,16 @@ static bool acpi_pci_bridge_d3(struct pcif (!dev->is_hotplug_bridge)return false; +/* Assume D3 support if the bridge is power-manageable by ACPI. */ + adev =ACPI_COMPANION (&dev->dev); +if (!adev && !pci_dev_is_added (dev)) { + adev =acpi_pci_find_companion (&dev->dev); +ACPI_COMPANION_SET (&dev->dev, adev); + } + +if (adev &&acpi_device_power_manageable (adev)) +return true; +/* * Look for a special _DSD property for the root port and if it * is set we know the hierarchy behind it supports D3 just fine.
Greg Kroah-Hartman
maintainerPATCH 210/391 ACPI: EC: PM: Flush EC work unconditionally after wakeup
In reply to Greg Kroah-HartmanFrom: Rafael J. Wysocki <[email protected]>
commit 5e92442bb4121562231e6daf8a2d1306cb5f8805 upstream.
Commit 607b9df63057 ("ACPI: EC: PM: Avoid flushing EC work when EC GPE is inactive") has been reported to cause some power button wakeup events to be missed on some systems, so modify acpi_ec_dispatch_gpe() to call acpi_ec_flush_work() unconditionally to effectively reverse the changes made by that commit.
Also note that the problem which prompted commit 607b9df63057 is not reproducible any more on the affected machine.
--- drivers/acpi/ec.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
drivers/acpi/ec.c +3 -4
@@ -2019,12 +2019,11 @@ bool acpi_ec_dispatch_gpe(void)* to allow the caller to process events properly after that. */ ret =acpi_dispatch_gpe (NULL , first_ec->gpe); -if (ret ==ACPI_INTERRUPT_HANDLED ) { +if (ret ==ACPI_INTERRUPT_HANDLED )pm_pr_dbg ("ACPI EC GPE dispatched\n" ); -/* Flush the event and query workqueues. */ -acpi_ec_flush_work (); - } +/* Flush the event and query workqueues. */ +acpi_ec_flush_work ();return false; }
Greg Kroah-Hartman
maintainerPATCH 211/391 ACPI: EC: PM: Drop ec_no_wakeup check from acpi_ec_dispatch_gpe()
In reply to Greg Kroah-HartmanFrom: Rafael J. Wysocki <[email protected]>
commit e0e9ce390d7bc6a705653d4a8aa4ea92c9a65e53 upstream.
It turns out that in some cases there are EC events to flush in acpi_ec_dispatch_gpe() even though the ec_no_wakeup kernel parameter is set and the EC GPE is disabled while sleeping, so drop the ec_no_wakeup check that prevents those events from being processed from acpi_ec_dispatch_gpe().
--- drivers/acpi/ec.c | 3 --- 1 file changed, 3 deletions(-)
drivers/acpi/ec.c +0 -3
@@ -2011,9 +2011,6 @@ bool acpi_ec_dispatch_gpe(void)if (acpi_any_gpe_status_set (first_ec->gpe))return true; -if (ec_no_wakeup) -return false; -/* * Dispatch the EC GPE in-band, but do not report wakeup in any case * to allow the caller to process events properly after that.
Greg Kroah-Hartman
maintainerPATCH 212/391 acpi-cpufreq: Honor _PSD table setting on new AMD CPUs
In reply to Greg Kroah-HartmanFrom: Wei Huang <[email protected]>
commit 5368512abe08a28525d9b24abbfc2a72493e8dba upstream.
acpi-cpufreq has a old quirk that overrides the _PSD table supplied by BIOS on AMD CPUs. However the _PSD table of new AMD CPUs (Family 19h+) now accurately reports the P-state dependency of CPU cores. Hence this quirk needs to be fixed in order to support new CPUs' frequency control.
--- drivers/cpufreq/acpi-cpufreq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/cpufreq/acpi-cpufreq.c +2 -1
@@ -691,7 +691,8 @@ static int acpi_cpufreq_cpu_init(structcpumask_copy (policy->cpus,topology_core_cpumask (cpu)); } -if (check_amd_hwpstate_cpu (cpu) && !acpi_pstate_strict) { +if (check_amd_hwpstate_cpu (cpu) && boot_cpu_data.x86 <0x19 && + !acpi_pstate_strict) {cpumask_clear (policy->cpus);cpumask_set_cpu (cpu, policy->cpus); cpumask_copy(data->freqdomain_cpus,
Greg Kroah-Hartman
maintainerPATCH 213/391 io-wq: assign NUMA node locality if appropriate
In reply to Greg Kroah-HartmanFrom: Jens Axboe <[email protected]>
commit a8b595b22d31f83b715511f59012f152a269d83b upstream.
There was an assumption that kthread_create_on_node() would properly set NUMA affinities in terms of CPUs allowed, but it doesn't. Make sure we do this when creating an io-wq context on NUMA.
Cc: [email protected]
Stefan Metzmacher <[email protected]>
--- fs/io-wq.c | 1 + 1 file changed, 1 insertion(+)
fs/io-wq.c +1 -0
@@ -654,6 +654,7 @@ static bool create_io_worker(struct io_wkfree (worker);return false; } +kthread_bind_mask (worker->task,cpumask_of_node (wqe->node));raw_spin_lock_irq (&wqe->lock);hlist_nulls_add_head_rcu (&worker->nulls_node, &wqe->free_list);
Greg Kroah-Hartman
maintainerPATCH 214/391 w1: mxc_w1: Fix timeout resolution problem leading to bus error
In reply to Greg Kroah-HartmanFrom: Martin Fuzzey <[email protected]>
commit c9723750a699c3bd465493ac2be8992b72ccb105 upstream.
On my platform (i.MX53) bus access sometimes fails with
w1_search: max_slave_count 64 reached, will continue next search.
The reason is the use of jiffies to implement a 200us timeout in mxc_w1_ds2_touch_bit().
On some platforms the jiffies timer resolution is insufficient for this.
Fix by replacing jiffies by ktime_get().
For consistency apply the same change to the other use of jiffies in mxc_w1_ds2_reset_bus().
--- drivers/w1/masters/mxc_w1.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/w1/masters/mxc_w1.c +7 -7
@@ -7,7 +7,7 @@#include <linux/clk.h> #include <linux/delay.h> #include <linux/io.h> -#include <linux/jiffies.h> +#include <linux/ktime.h> #include <linux/module.h> #include <linux/mod_devicetable.h> #include <linux/platform_device.h>
@@ -40,12 +40,12 @@ struct mxc_w1_device {static u8 mxc_w1_ds2_reset_bus (void *data) {struct mxc_w1_device *dev = data; -unsigned long timeout; +ktime_t timeout;writeb (MXC_W1_CONTROL_RPP , dev->regs +MXC_W1_CONTROL );/* Wait for reset sequence 511+512us, use 1500us for sure */ - timeout = jiffies +usecs_to_jiffies (1500 ); + timeout =ktime_add_us (ktime_get (),1500 );udelay (511 +512 );
@@ -55,7 +55,7 @@ static u8 mxc_w1_ds2_reset_bus(void *dat/* PST bit is valid after the RPP bit is self-cleared */ if (!(ctrl &MXC_W1_CONTROL_RPP ))return !(ctrl &MXC_W1_CONTROL_PST ); - }while (time_is_after_jiffies (timeout)); + }while (ktime_before (ktime_get (), timeout));return 1 ; }
@@ -68,12 +68,12 @@ static u8 mxc_w1_ds2_reset_bus(void *datstatic u8 mxc_w1_ds2_touch_bit (void *data,u8 bit) {struct mxc_w1_device *dev = data; -unsigned long timeout; +ktime_t timeout;writeb (MXC_W1_CONTROL_WR (bit), dev->regs +MXC_W1_CONTROL );/* Wait for read/write bit (60us, Max 120us), use 200us for sure */ - timeout = jiffies +usecs_to_jiffies (200 ); + timeout =ktime_add_us (ktime_get (),200 );udelay (60 );
@@ -83,7 +83,7 @@ static u8 mxc_w1_ds2_touch_bit(void *dat/* RDST bit is valid after the WR1/RD bit is self-cleared */ if (!(ctrl &MXC_W1_CONTROL_WR (bit)))return !!(ctrl &MXC_W1_CONTROL_RDST ); - }while (time_is_after_jiffies (timeout)); + }while (ktime_before (ktime_get (), timeout));return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 215/391 fs/kernel_read_file: Remove FIRMWARE_PREALLOC_BUFFER enum
In reply to Greg Kroah-HartmanFrom: Kees Cook <[email protected]>
commit c307459b9d1fcb8bbf3ea5a4162979532322ef77 upstream.
FIRMWARE_PREALLOC_BUFFER is a "how", not a "what", and confuses the LSMs that are interested in filtering between types of things. The "how" should be an internal detail made uninteresting to the LSMs.
--- drivers/base/firmware_loader/main.c | 5 ++--- fs/exec.c | 7 ++++--- include/linux/fs.h | 1 - kernel/module.c | 2 +- security/integrity/digsig.c | 2 +- security/integrity/ima/ima_fs.c | 2 +- security/integrity/ima/ima_main.c | 6 ++---- 7 files changed, 11 insertions(+), 14 deletions(-)
drivers/base/firmware_loader/main.c +2 -3
@@ -470,14 +470,12 @@ fw_get_filesystem_firmware(struct deviceint i, len;int rc = -ENOENT ;char *path; -enum kernel_read_file_id id =READING_FIRMWARE ;size_t msize =INT_MAX ;void *buffer =NULL ;/* Already populated data member means we're loading into a buffer */ if (!decompress && fw_priv->data) { buffer = fw_priv->data; - id =READING_FIRMWARE_PREALLOC_BUFFER ; msize = fw_priv->allocated_size; }
@@ -501,7 +499,8 @@ fw_get_filesystem_firmware(struct device/* load firmware files from the mount namespace of init */ rc =kernel_read_file_from_path_initns (path, &buffer, - &size, msize, id); + &size, msize, +READING_FIRMWARE );if (rc) {if (rc != -ENOENT ) dev_warn(device, "loading %s failed with error %d\n",
fs/exec.c +4 -3
@@ -955,6 +955,7 @@ int kernel_read_file(struct file *file, {loff_t i_size, pos;ssize_t bytes =0 ; +void *allocated =NULL ;int ret;if (!S_ISREG (file_inode (file)->i_mode) || max_size <0 )
@@ -978,8 +979,8 @@ int kernel_read_file(struct file *file, goto out; } -if (id !=READING_FIRMWARE_PREALLOC_BUFFER ) - *buf =vmalloc (i_size); +if (!*buf) + *buf = allocated =vmalloc (i_size);if (!*buf) { ret = -ENOMEM ; goto out;
@@ -1008,7 +1009,7 @@ int kernel_read_file(struct file *file, out_free:if (ret <0 ) { -if (id !=READING_FIRMWARE_PREALLOC_BUFFER ) { +if (allocated) {vfree (*buf); *buf =NULL ; }
include/linux/fs.h +0 -1
@@ -2861,7 +2861,6 @@ extern int do_pipe_flags(int *, int);#define __kernel_read_file_id (id) \ id(UNKNOWN, unknown) \ id(FIRMWARE, firmware) \ - id(FIRMWARE_PREALLOC_BUFFER, firmware) \ id(MODULE, kernel-module) \ id(KEXEC_IMAGE, kexec-image) \ id(KEXEC_INITRAMFS, kexec-initramfs) \
kernel/module.c +1 -1
@@ -4028,7 +4028,7 @@ SYSCALL_DEFINE3(finit_module, int, fd, c {struct load_info info = { };loff_t size; -void *hdr; +void *hdr =NULL ;int err; err =may_init_module ();
security/integrity/digsig.c +1 -1
@@ -169,7 +169,7 @@ int __init integrity_add_key(const unsigint __init integrity_load_x509 (const unsigned int id,const char *path) { -void *data; +void *data =NULL ;loff_t size;int rc;key_perm_t perm;
security/integrity/ima/ima_fs.c +1 -1
@@ -272,7 +272,7 @@ static const struct file_operations ima_static ssize_t ima_read_policy (char *path) { -void *data; +void *data =NULL ;char *datap;loff_t size;int rc, pathlen =strlen (path);
security/integrity/ima/ima_main.c +2 -4
@@ -621,19 +621,17 @@ void ima_post_path_mknod(struct dentry *int ima_read_file (struct file *file,enum kernel_read_file_id read_id) {/* -* READING_FIRMWARE_PREALLOC_BUFFER -* * Do devices using pre-allocated memory run the risk of the * firmware being accessible to the device prior to the completion * of IMA's signature verification any more than when using two -* buffers? +* buffers? It may be desirable to include the buffer address +* in this API and walk all the dma_map_single() mappings to check. */ return 0 ; }const int read_idmap[READING_MAX_ID ] = { [READING_FIRMWARE ] =FIRMWARE_CHECK , - [READING_FIRMWARE_PREALLOC_BUFFER ] =FIRMWARE_CHECK , [READING_MODULE ] =MODULE_CHECK , [READING_KEXEC_IMAGE ] =KEXEC_KERNEL_CHECK , [READING_KEXEC_INITRAMFS ] =KEXEC_INITRAMFS_CHECK ,
Greg Kroah-Hartman
maintainerPATCH 216/391 scsi: mptfusion: Fix null pointer dereferences in mptscsih_remove()
In reply to Greg Kroah-HartmanFrom: Helge Deller <[email protected]>
commit 2f4843b172c2c0360ee7792ad98025fae7baefde upstream.
The mptscsih_remove() function triggers a kernel oops if the Scsi_Host pointer (ioc->sh) is NULL, as can be seen in this syslog:
ioc0: LSI53C1030 B2: Capabilities={Initiator,Target}
Begin: Waiting for root file system ...
scsi host2: error handler thread failed to spawn, error = -4
mptspi: ioc0: WARNING - Unable to register controller with SCSI subsystem
Backtrace: [<000000001045b7cc>] mptspi_probe+0x248/0x3d0 [mptspi] [<0000000040946470>] pci_device_probe+0x1ac/0x2d8 [<0000000040add668>] really_probe+0x1bc/0x988 [<0000000040ade704>] driver_probe_device+0x160/0x218 [<0000000040adee24>] device_driver_attach+0x160/0x188 [<0000000040adef90>] __driver_attach+0x144/0x320 [<0000000040ad7c78>] bus_for_each_dev+0xd4/0x158 [<0000000040adc138>] driver_attach+0x4c/0x80 [<0000000040adb3ec>] bus_add_driver+0x3e0/0x498 [<0000000040ae0130>] driver_register+0xf4/0x298 [<00000000409450c4>] __pci_register_driver+0x78/0xa8 [<000000000007d248>] mptspi_init+0x18c/0x1c4 [mptspi]
This patch adds the necessary NULL-pointer checks. Successfully tested on a HP C8000 parisc workstation with buggy SCSI drives.
--- drivers/message/fusion/mptscsih.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/message/fusion/mptscsih.c +8 -5
@@ -1176,8 +1176,10 @@ mptscsih_remove(struct pci_dev *pdev)MPT_SCSI_HOST *hd;int sz1; -if ((hd =shost_priv (host)) ==NULL ) -return ; +if (host ==NULL ) + hd =NULL ; +else + hd =shost_priv (host);mptscsih_shutdown (pdev);
@@ -1193,14 +1195,15 @@ mptscsih_remove(struct pci_dev *pdev)"Free'd ScsiLookup (%d) memory\n" , ioc->name, sz1)); -kfree (hd->info_kbuf); +if (hd) +kfree (hd->info_kbuf);/* NULL the Scsi_Host pointer */ ioc->sh =NULL ; -scsi_host_put (host); - +if (host) +scsi_host_put (host);mpt_detach (pdev); }
Greg Kroah-Hartman
maintainerPATCH 217/391 scsi: qla2xxx: Fix MPI reset needed message
In reply to Greg Kroah-HartmanFrom: Arun Easi <[email protected]>
commit 7a6cdbd5e87515ebf6231b762ad903c7cff87b9c upstream.
When printing the message:
"MPI Heartbeat stop. MPI reset is not needed.."
..the wrong register was checked leading to always printing that MPI reset is not needed, even when it is needed. Fix the MPI reset message.
--- drivers/scsi/qla2xxx/qla_isr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/qla2xxx/qla_isr.c +1 -1
@@ -767,7 +767,7 @@ qla27xx_handle_8200_aen(scsi_qla_host_tql_log (ql_log_warn, vha,0x02f0 ,"MPI Heartbeat stop. MPI reset is%s needed. " "MB0[%xh] MB1[%xh] MB2[%xh] MB3[%xh]\n" , - mb[0 ] &BIT_8 ?"" :" not" , + mb[1 ] &BIT_8 ?"" :" not" , mb[0 ], mb[1 ], mb[2 ], mb[3 ]);if ((mb[1 ] &BIT_8 ) ==0 )
Greg Kroah-Hartman
maintainerPATCH 218/391 scsi: qla2xxx: Fix reset of MPI firmware
In reply to Greg Kroah-HartmanFrom: Arun Easi <[email protected]>
commit 3e6efab865ac943f4ec43913eb665695737112b0 upstream.
Normally, the MPI firmware is reset when an MPI dump is collected. If an unsaved MPI dump exists in the driver, though, an alternate mechanism is used. This mechanism, which was not fully correct, is not recommended and instead an MPI dump template walk is suggested to perform the MPI reset.
To allow for the MPI dump template walk, extra space is reserved in the MPI dump buffer which gets used only when there is already an MPI dump in place.
--- drivers/scsi/qla2xxx/qla_attr.c | 10 ++++++-- drivers/scsi/qla2xxx/qla_gbl.h | 1 drivers/scsi/qla2xxx/qla_init.c | 2 + drivers/scsi/qla2xxx/qla_tmpl.c | 49 ++++++++++------------------------------ 4 files changed, 23 insertions(+), 39 deletions(-)
drivers/scsi/qla2xxx/qla_attr.c +8 -2
@@ -157,6 +157,14 @@ qla2x00_sysfs_write_fw_dump(struct file vha->host_no); }break ; +case 10 : +if (IS_QLA27XX (ha) ||IS_QLA28XX (ha)) { +ql_log (ql_log_info, vha,0x70e9 , +"Issuing MPI firmware dump on host#%ld.\n" , + vha->host_no); + ha->isp_ops->mpi_fw_dump (vha,0 ); + } +break ; }return count; }
@@ -744,8 +752,6 @@ qla2x00_sysfs_write_reset(struct file *fqla83xx_idc_audit (vha,IDC_AUDIT_TIMESTAMP );qla83xx_idc_unlock (vha,0 );break ; - }else if (IS_QLA27XX (ha) ||IS_QLA28XX (ha)) { -qla27xx_reset_mpi (vha); }else {/* Make sure FC side is not in reset */ WARN_ON_ONCE(qla2x00_wait_for_hba_online(vha) !=
drivers/scsi/qla2xxx/qla_gbl.h +0 -1
@@ -938,6 +938,5 @@ extern void qla24xx_process_purex_list(s/* nvme.c */ void qla_nvme_unregister_remote_port (struct fc_port *fcport); -void qla27xx_reset_mpi (scsi_qla_host_t *vha);void qla_handle_els_plogi_done (scsi_qla_host_t *vha,struct event_arg *ea);#endif /* _QLA_GBL_H */
drivers/scsi/qla2xxx/qla_init.c +2 -0
@@ -3298,6 +3298,8 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *v j, fwdt->dump_size); dump_size += fwdt->dump_size; } +/* Add space for spare MPI fw dump. */ + dump_size += ha->fwdt[1 ].dump_size; }else { req_q_size = req->length *sizeof (request_t); rsp_q_size = rsp->length *sizeof (response_t);
drivers/scsi/qla2xxx/qla_tmpl.c +13 -36
84 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 219/391 scsi: qla2xxx: Fix crash on session cleanup with unload
In reply to Greg Kroah-HartmanFrom: Quinn Tran <[email protected]>
commit 50457dab670f396557e60c07f086358460876353 upstream.
On unload, session cleanup prematurely gave the signal for driver unload path to advance.
--- drivers/scsi/qla2xxx/qla_target.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/scsi/qla2xxx/qla_target.c +7 -6
@@ -1229,14 +1229,15 @@ void qlt_schedule_sess_for_deletion(strucase DSC_DELETE_PEND :return ;case DSC_DELETED : -if (tgt && tgt->tgt_stop && (tgt->sess_count ==0 )) -wake_up_all (&tgt->waitQ); -if (sess->vha->fcport_count ==0 ) -wake_up_all (&sess->vha->fcport_waitQ); -if (!sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN ] && - !sess->plogi_link[QLT_PLOGI_LINK_CONFLICT ]) + !sess->plogi_link[QLT_PLOGI_LINK_CONFLICT ]) { +if (tgt && tgt->tgt_stop && tgt->sess_count ==0 ) +wake_up_all (&tgt->waitQ); + +if (sess->vha->fcport_count ==0 ) +wake_up_all (&sess->vha->fcport_waitQ);return ; + }break ;case DSC_UPD_FCPORT :/*
Greg Kroah-Hartman
maintainerPATCH 220/391 PM: runtime: Remove link state checks in rpm_get/put_supplier()
In reply to Greg Kroah-HartmanFrom: Xiang Chen <[email protected]>
commit d12544fb2aa9944b180c35914031a8384ab082c1 upstream.
To support runtime PM for hisi SAS driver (the driver is in directory drivers/scsi/hisi_sas), we add device link between scsi_device->sdev_gendev (consumer device) and hisi_hba->dev(supplier device) with flags DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE.
After runtime suspended consumers and supplier, unload the dirver which causes a hung.
We found that it called function device_release_driver_internal() to release the supplier device (hisi_hba->dev), as the device link was busy, it set the device link state to DL_STATE_SUPPLIER_UNBIND, and then it called device_release_driver_internal() to release the consumer device (scsi_device->sdev_gendev).
Then it would try to call pm_runtime_get_sync() to resume the consumer device, but because consumer-supplier relation existed, it would try to resume the supplier first, but as the link state was already DL_STATE_SUPPLIER_UNBIND, so it skipped resuming the supplier and only resumed the consumer which hanged (it sends IOs to resume scsi_device while the SAS controller is suspended).
Simple flow is as follows:
device_release_driver_internal -> (supplier device)
if device_links_busy ->
device_links_unbind_consumers ->
...
WRITE_ONCE(link->status, DL_STATE_SUPPLIER_UNBIND)
device_release_driver_internal (consumer device)
pm_runtime_get_sync -> (consumer device)
...
__rpm_callback ->
rpm_get_suppliers ->
if link->state == DL_STATE_SUPPLIER_UNBIND -> skip the action of resuming the supplier
...
pm_runtime_clean_up_links
...Correct suspend/resume ordering between a supplier device and its consumer devices (resume the supplier device before resuming consumer devices, and suspend consumer devices before suspending the supplier device) should be guaranteed by runtime PM, but the state checks in rpm_get_supplier() and rpm_put_supplier() break this rule, so remove them.
--- drivers/base/power/runtime.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
drivers/base/power/runtime.c +1 -4
@@ -291,8 +291,7 @@ static int rpm_get_suppliers(struct devi device_links_read_lock_held()) {int retval; -if (!(link->flags &DL_FLAG_PM_RUNTIME ) || -READ_ONCE (link->status) ==DL_STATE_SUPPLIER_UNBIND ) +if (!(link->flags &DL_FLAG_PM_RUNTIME ))continue ; retval =pm_runtime_get_sync (link->supplier);
@@ -312,8 +311,6 @@ static void rpm_put_suppliers(struct devlist_for_each_entry_rcu (link, &dev->links.suppliers, c_node,device_links_read_lock_held ()) { -if (READ_ONCE (link->status) ==DL_STATE_SUPPLIER_UNBIND ) -continue ;while (refcount_dec_not_one (&link->rpm_active))pm_runtime_put (link->supplier);
Greg Kroah-Hartman
maintainerPATCH 221/391 btrfs: qgroup: fix wrong qgroup metadata reserve for delayed inode
In reply to Greg Kroah-HartmanFrom: Qu Wenruo <[email protected]>
commit b4c5d8fdfff3e2b6c4fa4a5043e8946dff500f8c upstream.
For delayed inode facility, qgroup metadata is reserved for it, and later freed.
However we're freeing more bytes than we reserved. In btrfs_delayed_inode_reserve_metadata():
num_bytes = btrfs_calc_metadata_size(fs_info, 1);
...
ret = btrfs_qgroup_reserve_meta_prealloc(root,
fs_info->nodesize, true);
...
if (!ret) {
node->bytes_reserved = num_bytes;But in btrfs_delayed_inode_release_metadata():
if (qgroup_free) btrfs_qgroup_free_meta_prealloc(node->root, node->bytes_reserved); else btrfs_qgroup_convert_reserved_meta(node->root, node->bytes_reserved);
This means, we're always releasing more qgroup metadata rsv than we have reserved.
This won't trigger selftest warning, as btrfs qgroup metadata rsv has extra protection against cases like quota enabled half-way.
But we still need to fix this problem any way.
This patch will use the same num_bytes for qgroup metadata rsv so we could handle it correctly.
--- fs/btrfs/delayed-inode.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
fs/btrfs/delayed-inode.c +1 -2
@@ -627,8 +627,7 @@ static int btrfs_delayed_inode_reserve_m*/ if (!src_rsv || (!trans->bytes_reserved && src_rsv->type !=BTRFS_BLOCK_RSV_DELALLOC )) { - ret =btrfs_qgroup_reserve_meta_prealloc (root, - fs_info->nodesize, true); + ret =btrfs_qgroup_reserve_meta_prealloc (root, num_bytes, true);if (ret <0 )return ret; ret = btrfs_block_rsv_add(root, dst_rsv, num_bytes,
Greg Kroah-Hartman
maintainerPATCH 222/391 btrfs: improve device scanning messages
In reply to Greg Kroah-HartmanFrom: Anand Jain <[email protected]>
commit 79dae17d8d44b2d15779e332180080af45df5352 upstream.
Systems booting without the initramfs seems to scan an unusual kind of device path (/dev/root). And at a later time, the device is updated to the correct path. We generally print the process name and PID of the process scanning the device but we don't capture the same information if the device path is rescanned with a different pathname.
The current message is too long, so drop the unnecessary UUID and add process name and PID.
While at this also update the duplicate device warning to include the process name and PID so the messages are consistent
CC: [email protected] # 4.19+
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=89721
--- fs/btrfs/volumes.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
fs/btrfs/volumes.c +8 -6
@@ -942,16 +942,18 @@ static noinline struct btrfs_device *devbdput (path_bdev);mutex_unlock (&fs_devices->device_list_mutex);btrfs_warn_in_rcu (device->fs_info, -"duplicate device fsid:devid for %pU:%llu old:%s new:%s" , - disk_super->fsid, devid, -rcu_str_deref (device->name), path); +"duplicate device %s devid %llu generation %llu scanned by %s (%d)" , + path, devid, found_transid, + current->comm, +task_pid_nr (current));return ERR_PTR (-EEXIST ); }bdput (path_bdev);btrfs_info_in_rcu (device->fs_info, -"device fsid %pU devid %llu moved old:%s new:%s" , - disk_super->fsid, devid, -rcu_str_deref (device->name), path); +"devid %llu device path %s changed to %s scanned by %s (%d)" , + devid,rcu_str_deref (device->name), + path, current->comm, +task_pid_nr (current)); } name =rcu_string_strdup (path,GFP_NOFS );
Greg Kroah-Hartman
maintainerPATCH 223/391 btrfs: qgroup: fix qgroup meta rsv leak for subvolume operations
In reply to Greg Kroah-HartmanFrom: Qu Wenruo <[email protected]>
commit e85fde5162bf1b242cbd6daf7dba0f9b457d592b upstream.
[BUG]
When quota is enabled for TEST_DEV, generic/013 sometimes fails like this:
generic/013 14s ... _check_dmesg: something found in dmesg (see xfstests-dev/results//generic/013.dmesg)
And with the following metadata leak:
BTRFS warning (device dm-3): qgroup 0/1370 has unreleased space, type 2 rsv 49152
------------[ cut here ]------------ WARNING: CPU: 2 PID: 47912 at fs/btrfs/disk-io.c:4078 close_ctree+0x1dc/0x323 [btrfs] Call Trace: btrfs_put_super+0x15/0x17 [btrfs] generic_shutdown_super+0x72/0x110 kill_anon_super+0x18/0x30 btrfs_kill_super+0x17/0x30 [btrfs] deactivate_locked_super+0x3b/0xa0 deactivate_super+0x40/0x50 cleanup_mnt+0x135/0x190 __cleanup_mnt+0x12/0x20 task_work_run+0x64/0xb0 __prepare_exit_to_usermode+0x1bc/0x1c0 __syscall_return_slowpath+0x47/0x230 do_syscall_64+0x64/0xb0 entry_SYSCALL_64_after_hwframe+0x44/0xa9 ---[ end trace a6cfd45ba80e4e06 ]--- BTRFS error (device dm-3): qgroup reserved space leaked BTRFS info (device dm-3): disk space caching is enabled BTRFS info (device dm-3): has skinny extents
[CAUSE]
The qgroup preallocated meta rsv operations of that offending root are:
btrfs_delayed_inode_reserve_metadata: rsv_meta_prealloc root=1370 num_bytes=131072 btrfs_delayed_inode_reserve_metadata: rsv_meta_prealloc root=1370 num_bytes=131072 btrfs_subvolume_reserve_metadata: rsv_meta_prealloc root=1370 num_bytes=49152 btrfs_delayed_inode_release_metadata: convert_meta_prealloc root=1370 num_bytes=-131072 btrfs_delayed_inode_release_metadata: convert_meta_prealloc root=1370 num_bytes=-131072
It's pretty obvious that, we reserve qgroup meta rsv in btrfs_subvolume_reserve_metadata(), but doesn't have corresponding release/convert calls in btrfs_subvolume_release_metadata().
This leads to the leakage.
[FIX]
To fix this bug, we should follow what we're doing in btrfs_delalloc_reserve_metadata(), where we reserve qgroup space, and add it to block_rsv->qgroup_rsv_reserved.
And free the qgroup reserved metadata space when releasing the block_rsv.
To do this, we need to change the btrfs_subvolume_release_metadata() to accept btrfs_root, and record the qgroup_to_release number, and call btrfs_qgroup_convert_reserved_meta() for it.
--- fs/btrfs/ctree.h | 2 +- fs/btrfs/inode.c | 2 +- fs/btrfs/ioctl.c | 6 +++--- fs/btrfs/root-tree.c | 13 +++++++++++-- 4 files changed, 16 insertions(+), 7 deletions(-)
fs/btrfs/ctree.h +1 -1
@@ -2619,7 +2619,7 @@ enum btrfs_flush_state {int btrfs_subvolume_reserve_metadata (struct btrfs_root *root,struct btrfs_block_rsv *rsv,int nitems,bool use_global_rsv); -void btrfs_subvolume_release_metadata (struct btrfs_fs_info *fs_info, +void btrfs_subvolume_release_metadata (struct btrfs_root *root,struct btrfs_block_rsv *rsv);void btrfs_delalloc_release_extents (struct btrfs_inode *inode,u64 num_bytes);
fs/btrfs/inode.c +1 -1
@@ -4051,7 +4051,7 @@ out_end_trans: err = ret; inode->i_flags |=S_DEAD ; out_release: -btrfs_subvolume_release_metadata (fs_info, &block_rsv); +btrfs_subvolume_release_metadata (root, &block_rsv); out_up_write:up_write (&fs_info->subvol_sem);if (err) {
fs/btrfs/ioctl.c +3 -3
@@ -618,7 +618,7 @@ static noinline int create_subvol(struct trans =btrfs_start_transaction (root,0 );if (IS_ERR (trans)) { ret =PTR_ERR (trans); -btrfs_subvolume_release_metadata (fs_info, &block_rsv); +btrfs_subvolume_release_metadata (root, &block_rsv); goto fail_free; } trans->block_rsv = &block_rsv;
@@ -742,7 +742,7 @@ fail:kfree (root_item); trans->block_rsv =NULL ; trans->bytes_reserved =0 ; -btrfs_subvolume_release_metadata (fs_info, &block_rsv); +btrfs_subvolume_release_metadata (root, &block_rsv); err =btrfs_commit_transaction (trans);if (err && !ret)
@@ -856,7 +856,7 @@ fail:if (ret && pending_snapshot->snap) pending_snapshot->snap->anon_dev =0 ;btrfs_put_root (pending_snapshot->snap); -btrfs_subvolume_release_metadata (fs_info, &pending_snapshot->block_rsv); +btrfs_subvolume_release_metadata (root, &pending_snapshot->block_rsv); free_pending:if (pending_snapshot->anon_dev)free_anon_bdev (pending_snapshot->anon_dev);
fs/btrfs/root-tree.c +11 -2
@@ -512,11 +512,20 @@ int btrfs_subvolume_reserve_metadata(strif (ret && qgroup_num_bytes)btrfs_qgroup_free_meta_prealloc (root, qgroup_num_bytes); +if (!ret) { +spin_lock (&rsv->lock); + rsv->qgroup_rsv_reserved += qgroup_num_bytes; +spin_unlock (&rsv->lock); + }return ret; } -void btrfs_subvolume_release_metadata (struct btrfs_fs_info *fs_info, +void btrfs_subvolume_release_metadata (struct btrfs_root *root,struct btrfs_block_rsv *rsv) { -btrfs_block_rsv_release (fs_info, rsv, (u64)-1 ,NULL ); +struct btrfs_fs_info *fs_info = root->fs_info; +u64 qgroup_to_release; + +btrfs_block_rsv_release (fs_info, rsv, (u64)-1 , &qgroup_to_release); +btrfs_qgroup_convert_reserved_meta (root, qgroup_to_release); }
Greg Kroah-Hartman
maintainerPATCH 224/391 btrfs: sysfs: init devices outside of the chunk_mutex
In reply to Greg Kroah-HartmanFrom: Josef Bacik <[email protected]>
commit ca10845a56856fff4de3804c85e6424d0f6d0cde upstream.
While running btrfs/061, btrfs/073, btrfs/078, or btrfs/178 we hit the following lockdep splat:
======================================================
WARNING: possible circular locking dependency detected
5.9.0-rc3+ #4 Not tainted
------------------------------------------------------
kswapd0/100 is trying to acquire lock:
ffff96ecc22ef4a0 (&delayed_node->mutex){+.+.}-{3:3}, at: __btrfs_release_delayed_node.part.0+0x3f/0x330
but task is already holding lock:
ffffffff8dd74700 (fs_reclaim){+.+.}-{0:0}, at: __fs_reclaim_acquire+0x5/0x30
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #3 (fs_reclaim){+.+.}-{0:0}:
fs_reclaim_acquire+0x65/0x80 slab_pre_alloc_hook.constprop.0+0x20/0x200 kmem_cache_alloc+0x37/0x270 alloc_inode+0x82/0xb0 iget_locked+0x10d/0x2c0 kernfs_get_inode+0x1b/0x130 kernfs_get_tree+0x136/0x240 sysfs_get_tree+0x16/0x40 vfs_get_tree+0x28/0xc0 path_mount+0x434/0xc00 __x64_sys_mount+0xe3/0x120 do_syscall_64+0x33/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xa9
-> #2 (kernfs_mutex){+.+.}-{3:3}:
__mutex_lock+0x7e/0x7e0 kernfs_add_one+0x23/0x150 kernfs_create_link+0x63/0xa0 sysfs_do_create_link_sd+0x5e/0xd0 btrfs_sysfs_add_devices_dir+0x81/0x130 btrfs_init_new_device+0x67f/0x1250 btrfs_ioctl+0x1ef/0x2e20 __x64_sys_ioctl+0x83/0xb0 do_syscall_64+0x33/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xa9
-> #1 (&fs_info->chunk_mutex){+.+.}-{3:3}:
__mutex_lock+0x7e/0x7e0 btrfs_chunk_alloc+0x125/0x3a0 find_free_extent+0xdf6/0x1210 btrfs_reserve_extent+0xb3/0x1b0 btrfs_alloc_tree_block+0xb0/0x310 alloc_tree_block_no_bg_flush+0x4a/0x60 __btrfs_cow_block+0x11a/0x530 btrfs_cow_block+0x104/0x220 btrfs_search_slot+0x52e/0x9d0 btrfs_insert_empty_items+0x64/0xb0 btrfs_insert_delayed_items+0x90/0x4f0 btrfs_commit_inode_delayed_items+0x93/0x140 btrfs_log_inode+0x5de/0x2020 btrfs_log_inode_parent+0x429/0xc90 btrfs_log_new_name+0x95/0x9b btrfs_rename2+0xbb9/0x1800 vfs_rename+0x64f/0x9f0 do_renameat2+0x320/0x4e0 __x64_sys_rename+0x1f/0x30 do_syscall_64+0x33/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xa9
-> #0 (&delayed_node->mutex){+.+.}-{3:3}:
__lock_acquire+0x119c/0x1fc0 lock_acquire+0xa7/0x3d0 __mutex_lock+0x7e/0x7e0 __btrfs_release_delayed_node.part.0+0x3f/0x330 btrfs_evict_inode+0x24c/0x500 evict+0xcf/0x1f0 dispose_list+0x48/0x70 prune_icache_sb+0x44/0x50 super_cache_scan+0x161/0x1e0 do_shrink_slab+0x178/0x3c0 shrink_slab+0x17c/0x290 shrink_node+0x2b2/0x6d0 balance_pgdat+0x30a/0x670 kswapd+0x213/0x4c0 kthread+0x138/0x160 ret_from_fork+0x1f/0x30
other info that might help us debug this:
Chain exists of:
&delayed_node->mutex --> kernfs_mutex --> fs_reclaim
Possible unsafe locking scenario: CPU0 CPU1
---- ----
lock(fs_reclaim);
lock(kernfs_mutex);
lock(fs_reclaim);
lock(&delayed_node->mutex);*** DEADLOCK ***
3 locks held by kswapd0/100:
#0: ffffffff8dd74700 (fs_reclaim){+.+.}-{0:0}, at: __fs_reclaim_acquire+0x5/0x30 #1: ffffffff8dd65c50 (shrinker_rwsem){++++}-{3:3}, at: shrink_slab+0x115/0x290 #2: ffff96ed2ade30e0 (&type->s_umount_key#36){++++}-{3:3}, at: super_cache_scan+0x38/0x1e0
stack backtrace: CPU: 0 PID: 100 Comm: kswapd0 Not tainted 5.9.0-rc3+ #4 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-2.fc32 04/01/2014 Call Trace: dump_stack+0x8b/0xb8 check_noncircular+0x12d/0x150 __lock_acquire+0x119c/0x1fc0 lock_acquire+0xa7/0x3d0 ? __btrfs_release_delayed_node.part.0+0x3f/0x330 __mutex_lock+0x7e/0x7e0 ? __btrfs_release_delayed_node.part.0+0x3f/0x330 ? __btrfs_release_delayed_node.part.0+0x3f/0x330 ? lock_acquire+0xa7/0x3d0 ? find_held_lock+0x2b/0x80 __btrfs_release_delayed_node.part.0+0x3f/0x330 btrfs_evict_inode+0x24c/0x500 evict+0xcf/0x1f0 dispose_list+0x48/0x70 prune_icache_sb+0x44/0x50 super_cache_scan+0x161/0x1e0 do_shrink_slab+0x178/0x3c0 shrink_slab+0x17c/0x290 shrink_node+0x2b2/0x6d0 balance_pgdat+0x30a/0x670 kswapd+0x213/0x4c0 ? _raw_spin_unlock_irqrestore+0x41/0x50 ? add_wait_queue_exclusive+0x70/0x70 ? balance_pgdat+0x670/0x670 kthread+0x138/0x160 ? kthread_create_worker_on_cpu+0x40/0x40 ret_from_fork+0x1f/0x30
This happens because we are holding the chunk_mutex at the time of adding in a new device. However we only need to hold the device_list_mutex, as we're going to iterate over the fs_devices devices. Move the sysfs init stuff outside of the chunk_mutex to get rid of this lockdep splat.
--- fs/btrfs/volumes.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
fs/btrfs/volumes.c +4 -3
@@ -2613,9 +2613,6 @@ int btrfs_init_new_device(struct btrfs_fbtrfs_set_super_num_devices (fs_info->super_copy, orig_super_num_devices +1 ); -/* add sysfs device entry */ -btrfs_sysfs_add_devices_dir (fs_devices, device); -/* * we've got more storage, clear any full flags on the space * infos
@@ -2623,6 +2620,10 @@ int btrfs_init_new_device(struct btrfs_fbtrfs_clear_space_info_full (fs_info);mutex_unlock (&fs_info->chunk_mutex); + +/* Add sysfs device entry */ +btrfs_sysfs_add_devices_dir (fs_devices, device); +mutex_unlock (&fs_devices->device_list_mutex);if (seeding_dev) {
Greg Kroah-Hartman
maintainerPATCH 225/391 btrfs: tracepoints: output proper root owner for trace_find_free_extent()
In reply to Greg Kroah-HartmanFrom: Qu Wenruo <[email protected]>
commit 437490fed3b0c9ae21af8f70e0f338d34560842b upstream.
The current trace event always output result like this:
find_free_extent: root=2(EXTENT_TREE) len=16384 empty_size=0 flags=4(METADATA)
find_free_extent: root=2(EXTENT_TREE) len=16384 empty_size=0 flags=4(METADATA)
find_free_extent: root=2(EXTENT_TREE) len=8192 empty_size=0 flags=1(DATA)
find_free_extent: root=2(EXTENT_TREE) len=8192 empty_size=0 flags=1(DATA)
find_free_extent: root=2(EXTENT_TREE) len=4096 empty_size=0 flags=1(DATA)
find_free_extent: root=2(EXTENT_TREE) len=4096 empty_size=0 flags=1(DATA)
T's saying we're allocating data extent for EXTENT tree, which is not even possible.
It's because we always use EXTENT tree as the owner for trace_find_free_extent() without using the @root from btrfs_reserve_extent().
This patch will change the parameter to use proper @root for trace_find_free_extent():
Now it looks much better:
find_free_extent: root=5(FS_TREE) len=16384 empty_size=0 flags=36(METADATA|DUP)
find_free_extent: root=5(FS_TREE) len=8192 empty_size=0 flags=1(DATA)
find_free_extent: root=5(FS_TREE) len=16384 empty_size=0 flags=1(DATA)
find_free_extent: root=5(FS_TREE) len=4096 empty_size=0 flags=1(DATA)
find_free_extent: root=5(FS_TREE) len=8192 empty_size=0 flags=1(DATA)
find_free_extent: root=5(FS_TREE) len=16384 empty_size=0 flags=36(METADATA|DUP)
find_free_extent: root=7(CSUM_TREE) len=16384 empty_size=0 flags=36(METADATA|DUP)
find_free_extent: root=2(EXTENT_TREE) len=16384 empty_size=0 flags=36(METADATA|DUP)
find_free_extent: root=1(ROOT_TREE) len=16384 empty_size=0 flags=36(METADATA|DUP)
--- fs/btrfs/extent-tree.c | 7 ++++--- include/trace/events/btrfs.h | 10 ++++++---- 2 files changed, 10 insertions(+), 7 deletions(-)
fs/btrfs/extent-tree.c +4 -3
@@ -3918,11 +3918,12 @@ static int prepare_allocation(struct btr* |- Push harder to find free extents * |- If not found, re-iterate all block groups */ -static noinline int find_free_extent(struct btrfs_fs_info *fs_info, +static noinline int find_free_extent(struct btrfs_root *root,u64 ram_bytes,u64 num_bytes,u64 empty_size,u64 hint_byte_orig,struct btrfs_key *ins,u64 flags,int delalloc) { +struct btrfs_fs_info *fs_info = root->fs_info;int ret =0 ;int cache_block_group_error =0 ;struct btrfs_block_group *block_group =NULL ;
@@ -3954,7 +3955,7 @@ static noinline int find_free_extent(str ins->objectid =0 ; ins->offset =0 ; -trace_find_free_extent (fs_info, num_bytes, empty_size, flags); +trace_find_free_extent (root, num_bytes, empty_size, flags); space_info =btrfs_find_space_info (fs_info, flags);if (!space_info) {
@@ -4203,7 +4204,7 @@ int btrfs_reserve_extent(struct btrfs_ro flags =get_alloc_profile_by_root (root, is_data); again:WARN_ON (num_bytes < fs_info->sectorsize); - ret =find_free_extent (fs_info, ram_bytes, num_bytes, empty_size, + ret =find_free_extent (root, ram_bytes, num_bytes, empty_size, hint_byte, ins, flags, delalloc);if (!ret && !is_data) {btrfs_dec_block_group_reservations (fs_info, ins->objectid);
include/trace/events/btrfs.h +6 -4
@@ -1176,25 +1176,27 @@ DEFINE_EVENT(btrfs__reserved_extent, btTRACE_EVENT (find_free_extent, - TP_PROTO(const struct btrfs_fs_info *fs_info, u64 num_bytes, + TP_PROTO(const struct btrfs_root *root, u64 num_bytes, u64 empty_size, u64 data), -TP_ARGS (fs_info, num_bytes, empty_size, data), +TP_ARGS (root, num_bytes, empty_size, data),TP_STRUCT__entry_btrfs ( + __field( u64, root_objectid ) __field( u64, num_bytes ) __field( u64, empty_size )__field ( u64, data ) ), -TP_fast_assign_btrfs (fs_info, +TP_fast_assign_btrfs (root->fs_info, + __entry->root_objectid = root->root_key.objectid; __entry->num_bytes = num_bytes; __entry->empty_size = empty_size; __entry->data = data; ),TP_printk_btrfs ("root=%llu(%s) len=%llu empty_size=%llu flags=%llu(%s)" , -show_root_type (BTRFS_EXTENT_TREE_OBJECTID ), +show_root_type (__entry->root_objectid), __entry->num_bytes, __entry->empty_size, __entry->data,__print_flags ((unsigned long )__entry->data,"|" , BTRFS_GROUP_FLAGS))
Greg Kroah-Hartman
maintainerPATCH 226/391 btrfs: reschedule if necessary when logging directory items
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
commit bb56f02f26fe23798edb1b2175707419b28c752a upstream.
Logging directories with many entries can take a significant amount of time, and in some cases monopolize a cpu/core for a long time if the logging task doesn't happen to block often enough.
Johannes and Lu Fengqi reported test case generic/041 triggering a soft lockup when the kernel has CONFIG_SOFTLOCKUP_DETECTOR=y. For this test case we log an inode with 3002 hard links, and because the test removed one hard link before fsyncing the file, the inode logging causes the parent directory do be logged as well, which has 6004 directory items to log (3002 BTRFS_DIR_ITEM_KEY items plus 3002 BTRFS_DIR_INDEX_KEY items), so it can take a significant amount of time and trigger the soft lockup.
So just make tree-log.c:log_dir_items() reschedule when necessary, releasing the current search path before doing so and then resume from where it was before the reschedule.
The stack trace produced when the soft lockup happens is the following:
[10480.277653] watchdog: BUG: soft lockup - CPU#2 stuck for 22s! [xfs_io:28172] [10480.279418] Modules linked in: dm_thin_pool dm_persistent_data (...) [10480.284915] irq event stamp: 29646366 [10480.285987] hardirqs last enabled at (29646365): [<ffffffff85249b66>] __slab_alloc.constprop.0+0x56/0x60 [10480.288482] hardirqs last disabled at (29646366): [<ffffffff8579b00d>] irqentry_enter+0x1d/0x50 [10480.290856] softirqs last enabled at (4612): [<ffffffff85a00323>] __do_softirq+0x323/0x56c [10480.293615] softirqs last disabled at (4483): [<ffffffff85800dbf>] asm_call_on_stack+0xf/0x20 [10480.296428] CPU: 2 PID: 28172 Comm: xfs_io Not tainted 5.9.0-rc4-default+ #1248 [10480.298948] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-59-gc9ba527-rebuilt.opensuse.org 04/01/2014 [10480.302455] RIP: 0010:__slab_alloc.constprop.0+0x19/0x60 [10480.304151] Code: 86 e8 31 75 21 00 66 66 2e 0f 1f 84 00 00 00 (...) [10480.309558] RSP: 0018:ffffadbe09397a58 EFLAGS: 00000282 [10480.311179] RAX: ffff8a495ab92840 RBX: 0000000000000282 RCX: 0000000000000006 [10480.313242] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffffff85249b66 [10480.315260] RBP: ffff8a497d04b740 R08: 0000000000000001 R09: 0000000000000001 [10480.317229] R10: ffff8a497d044800 R11: ffff8a495ab93c40 R12: 0000000000000000 [10480.319169] R13: 0000000000000000 R14: 0000000000000c40 R15: ffffffffc01daf70 [10480.321104] FS: 00007fa1dc5c0e40(0000) GS:ffff8a497da00000(0000) knlGS:0000000000000000 [10480.323559] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [10480.325235] CR2: 00007fa1dc5befb8 CR3: 0000000004f8a006 CR4: 0000000000170ea0 [10480.327259] Call Trace: [10480.328286] ? overwrite_item+0x1f0/0x5a0 [btrfs] [10480.329784] __kmalloc+0x831/0xa20 [10480.331009] ? btrfs_get_32+0xb0/0x1d0 [btrfs] [10480.332464] overwrite_item+0x1f0/0x5a0 [btrfs] [10480.333948] log_dir_items+0x2ee/0x570 [btrfs] [10480.335413] log_directory_changes+0x82/0xd0 [btrfs] [10480.336926] btrfs_log_inode+0xc9b/0xda0 [btrfs] [10480.338374] ? init_once+0x20/0x20 [btrfs] [10480.339711] btrfs_log_inode_parent+0x8d3/0xd10 [btrfs] [10480.341257] ? dget_parent+0x97/0x2e0 [10480.342480] btrfs_log_dentry_safe+0x3a/0x50 [btrfs] [10480.343977] btrfs_sync_file+0x24b/0x5e0 [btrfs] [10480.345381] do_fsync+0x38/0x70 [10480.346483] __x64_sys_fsync+0x10/0x20 [10480.347703] do_syscall_64+0x2d/0x70 [10480.348891] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [10480.350444] RIP: 0033:0x7fa1dc80970b [10480.351642] Code: 0f 05 48 3d 00 f0 ff ff 77 45 c3 0f 1f 40 00 48 (...) [10480.356952] RSP: 002b:00007fffb3d081d0 EFLAGS: 00000293 ORIG_RAX: 000000000000004a [10480.359458] RAX: ffffffffffffffda RBX: 0000562d93d45e40 RCX: 00007fa1dc80970b [10480.361426] RDX: 0000562d93d44ab0 RSI: 0000562d93d45e60 RDI: 0000000000000003 [10480.363367] RBP: 0000000000000001 R08: 0000000000000000 R09: 00007fa1dc7b2a40 [10480.365317] R10: 0000562d93d0e366 R11: 0000000000000293 R12: 0000000000000001 [10480.367299] R13: 0000562d93d45290 R14: 0000562d93d45e40 R15: 0000562d93d45e60
--- fs/btrfs/tree-log.c | 8 ++++++++ 1 file changed, 8 insertions(+)
fs/btrfs/tree-log.c +8 -0
@@ -3615,6 +3615,7 @@ static noinline int log_dir_items(struct* search and this search we'll not find the key again and can just * bail. */ +search: ret =btrfs_search_slot (NULL , root, &min_key, path,0 ,0 );if (ret !=0 ) goto done;
@@ -3634,6 +3635,13 @@ static noinline int log_dir_items(structif (min_key.objectid != ino || min_key.type != key_type) goto done; + +if (need_resched ()) { +btrfs_release_path (path); +cond_resched (); + goto search; + } + ret =overwrite_item (trans, log, dst_path, src, i, &min_key);if (ret) {
Greg Kroah-Hartman
maintainerPATCH 227/391 btrfs: send, orphanize first all conflicting inodes when processing references
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
commit 98272bb77bf4cc20ed1ffca89832d713e70ebf09 upstream.
When doing an incremental send it is possible that when processing the new references for an inode we end up issuing rename or link operations that have an invalid path, which contains the orphanized name of a directory before we actually orphanized it, causing the receiver to fail.
The following reproducer triggers such scenario:
$ cat reproducer.sh #!/bin/bash
mkfs.btrfs -f /dev/sdi >/dev/null
mount /dev/sdi /mnt/sdi
touch /mnt/sdi/a
touch /mnt/sdi/b
mkdir /mnt/sdi/testdir
# We want "a" to have a lower inode number then "testdir" (257 vs 259). mv /mnt/sdi/a /mnt/sdi/testdir/a
# Filesystem looks like:
#
# . (ino 256) # |----- testdir/ (ino 259) # | |----- a (ino 257) # | # |----- b (ino 258)
btrfs subvolume snapshot -r /mnt/sdi /mnt/sdi/snap1 btrfs send -f /tmp/snap1.send /mnt/sdi/snap1
# Now rename 259 to "testdir_2", then change the name of 257 to # "testdir" and make it a direct descendant of the root inode (256). # Also create a new link for inode 257 with the old name of inode 258. # By swapping the names and location of several inodes and create a
# nasty dependency chain of rename and link operations. mv /mnt/sdi/testdir/a /mnt/sdi/a2 touch /mnt/sdi/testdir/a mv /mnt/sdi/b /mnt/sdi/b2 ln /mnt/sdi/a2 /mnt/sdi/b mv /mnt/sdi/testdir /mnt/sdi/testdir_2 mv /mnt/sdi/a2 /mnt/sdi/testdir
# Filesystem now looks like:
#
# . (ino 256) # |----- testdir_2/ (ino 259) # | |----- a (ino 260) # | # |----- testdir (ino 257) # |----- b (ino 257) # |----- b2 (ino 258)
btrfs subvolume snapshot -r /mnt/sdi /mnt/sdi/snap2 btrfs send -f /tmp/snap2.send -p /mnt/sdi/snap1 /mnt/sdi/snap2
mkfs.btrfs -f /dev/sdj >/dev/null
mount /dev/sdj /mnt/sdj
btrfs receive -f /tmp/snap1.send /mnt/sdj
btrfs receive -f /tmp/snap2.send /mnt/sdj
umount /mnt/sdi
umount /mnt/sdj
When running the reproducer, the receive of the incremental send stream fails:
$ ./reproducer.sh Create a readonly snapshot of '/mnt/sdi' in '/mnt/sdi/snap1' At subvol /mnt/sdi/snap1 Create a readonly snapshot of '/mnt/sdi' in '/mnt/sdi/snap2' At subvol /mnt/sdi/snap2 At subvol snap1 At snapshot snap2 ERROR: link b -> o259-6-0/a failed: No such file or directory
The problem happens because of the following:
1) Before we start iterating the list of new references for inode 257, we generate its current path and store it at @valid_path, done at the very beginning of process_recorded_refs(). The generated path is "o259-6-0/a", containing the orphanized name for inode 259;
2) Then we iterate over the list of new references, which has the references "b" and "testdir" in that specific order;
3) We process reference "b" first, because it is in the list before reference "testdir". We then issue a link operation to create the new reference "b" using a target path corresponding to the content at @valid_path, which corresponds to "o259-6-0/a". However we haven't yet orphanized inode 259, its name is still "testdir", and not "o259-6-0". The orphanization of 259 did not happen yet because we will process the reference named "testdir" for inode 257 only in the next iteration of the loop that goes over the list of new references.
Fix the issue by having a preliminar iteration over all the new references at process_recorded_refs(). This iteration is responsible only for doing the orphanization of other inodes that have and old reference that conflicts with one of the new references of the inode we are currently processing. The emission of rename and link operations happen now in the next iteration of the new references.
A test case for fstests will follow soon.
--- fs/btrfs/send.c | 127 ++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 87 insertions(+), 40 deletions(-)
fs/btrfs/send.c +87 -40
@@ -3880,52 +3880,56 @@ static int process_recorded_refs(struct goto out; } +/* +* Before doing any rename and link operations, do a first pass on the +* new references to orphanize any unprocessed inodes that may have a +* reference that conflicts with one of the new references of the current +* inode. This needs to happen first because a new reference may conflict +* with the old reference of a parent directory, so we must make sure +* that the path used for link and rename commands don't use an +* orphanized name when an ancestor was not yet orphanized. +* +* Example: +* +* Parent snapshot: +* +* . (ino 256) +* |----- testdir/ (ino 259) +* | |----- a (ino 257) +* | +* |----- b (ino 258) +* +* Send snapshot: +* +* . (ino 256) +* |----- testdir_2/ (ino 259) +* | |----- a (ino 260) +* | +* |----- testdir (ino 257) +* |----- b (ino 257) +* |----- b2 (ino 258) +* +* Processing the new reference for inode 257 with name "b" may happen +* before processing the new reference with name "testdir". If so, we +* must make sure that by the time we send a link command to create the +* hard link "b", inode 259 was already orphanized, since the generated +* path in "valid_path" already contains the orphanized name for 259. +* We are processing inode 257, so only later when processing 259 we do +* the rename operation to change its temporary (orphanized) name to +* "testdir_2". +*/ list_for_each_entry (cur, &sctx->new_refs, list) { -/* -* We may have refs where the parent directory does not exist -* yet. This happens if the parent directories inum is higher -* than the current inum. To handle this case, we create the -* parent directory out of order. But we need to check if this -* did already happen before due to other refs in the same dir. -*/ ret =get_cur_inode_state (sctx, cur->dir, cur->dir_gen);if (ret <0 ) goto out; -if (ret == inode_state_will_create) { - ret =0 ; -/* -* First check if any of the current inodes refs did -* already create the dir. -*/ -list_for_each_entry (cur2, &sctx->new_refs, list) { -if (cur == cur2) -break ; -if (cur2->dir == cur->dir) { - ret =1 ; -break ; - } - } - -/* -* If that did not happen, check if a previous inode -* did already create the dir. -*/ -if (!ret) - ret =did_create_dir (sctx, cur->dir); -if (ret <0 ) - goto out; -if (!ret) { - ret =send_create_inode (sctx, cur->dir); -if (ret <0 ) - goto out; - } - } +if (ret == inode_state_will_create) +continue ;/* -* Check if this new ref would overwrite the first ref of -* another unprocessed inode. If yes, orphanize the -* overwritten inode. If we find an overwritten ref that is -* not the first ref, simply unlink it. +* Check if this new ref would overwrite the first ref of another +* unprocessed inode. If yes, orphanize the overwritten inode. +* If we find an overwritten ref that is not the first ref, +* simply unlink it. */ ret = will_overwrite_ref(sctx, cur->dir, cur->dir_gen, cur->name, cur->name_len,
@@ -4002,6 +4006,49 @@ static int process_recorded_refs(structif (ret <0 ) goto out; } + } + + } + +list_for_each_entry (cur, &sctx->new_refs, list) { +/* +* We may have refs where the parent directory does not exist +* yet. This happens if the parent directories inum is higher +* than the current inum. To handle this case, we create the +* parent directory out of order. But we need to check if this +* did already happen before due to other refs in the same dir. +*/ + ret =get_cur_inode_state (sctx, cur->dir, cur->dir_gen); +if (ret <0 ) + goto out; +if (ret == inode_state_will_create) { + ret =0 ; +/* +* First check if any of the current inodes refs did +* already create the dir. +*/ +list_for_each_entry (cur2, &sctx->new_refs, list) { +if (cur == cur2) +break ; +if (cur2->dir == cur->dir) { + ret =1 ; +break ; + } + } + +/* +* If that did not happen, check if a previous inode +* did already create the dir. +*/ +if (!ret) + ret =did_create_dir (sctx, cur->dir); +if (ret <0 ) + goto out; +if (!ret) { + ret =send_create_inode (sctx, cur->dir); +if (ret <0 ) + goto out; + } }if (S_ISDIR (sctx->cur_inode_mode) && sctx->parent_root) {
Greg Kroah-Hartman
maintainerPATCH 228/391 btrfs: send, recompute reference path after orphanization of a directory
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
commit 9c2b4e0347067396ceb3ae929d6888c81d610259 upstream.
During an incremental send, when an inode has multiple new references we might end up emitting rename operations for orphanizations that have a source path that is no longer valid due to a previous orphanization of some directory inode. This causes the receiver to fail since it tries to rename a path that does not exists.
Example reproducer:
$ cat reproducer.sh #!/bin/bash
mkfs.btrfs -f /dev/sdi >/dev/null
mount /dev/sdi /mnt/sdi
touch /mnt/sdi/f1
touch /mnt/sdi/f2
mkdir /mnt/sdi/d1
mkdir /mnt/sdi/d1/d2
# Filesystem looks like:
#
# . (ino 256) # |----- f1 (ino 257) # |----- f2 (ino 258) # |----- d1/ (ino 259) # |----- d2/ (ino 260)
btrfs subvolume snapshot -r /mnt/sdi /mnt/sdi/snap1 btrfs send -f /tmp/snap1.send /mnt/sdi/snap1
# Now do a series of changes such that:
#
# *) inode 258 has one new hardlink and the previous name changed #
# *) both names conflict with the old names of two other inodes:
#
# 1) the new name "d1" conflicts with the old name of inode 259,
# under directory inode 256 (root)
#
# 2) the new name "d2" conflicts with the old name of inode 260
# under directory inode 259
#
# *) inodes 259 and 260 now have the old names of inode 258 #
# *) inode 257 is now located under inode 260 - an inode with a number
# smaller than the inode (258) for which we created a second hard
# link and swapped its names with inodes 259 and 260
#
ln /mnt/sdi/f2 /mnt/sdi/d1/f2_link
mv /mnt/sdi/f1 /mnt/sdi/d1/d2/f1
# Swap d1 and f2.
mv /mnt/sdi/d1 /mnt/sdi/tmp
mv /mnt/sdi/f2 /mnt/sdi/d1
mv /mnt/sdi/tmp /mnt/sdi/f2
# Swap d2 and f2_link
mv /mnt/sdi/f2/d2 /mnt/sdi/tmp
mv /mnt/sdi/f2/f2_link /mnt/sdi/f2/d2
mv /mnt/sdi/tmp /mnt/sdi/f2/f2_link
# Filesystem now looks like:
#
# . (ino 256) # |----- d1 (ino 258) # |----- f2/ (ino 259) # |----- f2_link/ (ino 260) # | |----- f1 (ino 257) # | # |----- d2 (ino 258)
btrfs subvolume snapshot -r /mnt/sdi /mnt/sdi/snap2 btrfs send -f /tmp/snap2.send -p /mnt/sdi/snap1 /mnt/sdi/snap2
mkfs.btrfs -f /dev/sdj >/dev/null
mount /dev/sdj /mnt/sdj
btrfs receive -f /tmp/snap1.send /mnt/sdj
btrfs receive -f /tmp/snap2.send /mnt/sdj
umount /mnt/sdi
umount /mnt/sdj
When executed the receive of the incremental stream fails:
$ ./reproducer.sh Create a readonly snapshot of '/mnt/sdi' in '/mnt/sdi/snap1' At subvol /mnt/sdi/snap1 Create a readonly snapshot of '/mnt/sdi' in '/mnt/sdi/snap2' At subvol /mnt/sdi/snap2 At subvol snap1 At snapshot snap2 ERROR: rename d1/d2 -> o260-6-0 failed: No such file or directory
This happens because:
1) When processing inode 257 we end up computing the name for inode 259 because it is an ancestor in the send snapshot, and at that point it still has its old name, "d1", from the parent snapshot because inode 259 was not yet processed. We then cache that name, which is valid until we start processing inode 259 (or set the progress to 260 after processing its references);
2) Later we start processing inode 258 and collecting all its new references into the list sctx->new_refs. The first reference in the list happens to be the reference for name "d1" while the reference for name "d2" is next (the last element of the list).
We compute the full path "d1/d2" for this second reference and store it in the reference (its ->full_path member). The path used for the new parent directory was "d1" and not "f2" because inode 259, the new parent, was not yet processed;
3) When we start processing the new references at process_recorded_refs() we start with the first reference in the list, for the new name "d1". Because there is a conflicting inode that was not yet processed, which is directory inode 259, we orphanize it, renaming it from "d1" to "o259-6-0";
4) Then we start processing the new reference for name "d2", and we realize it conflicts with the reference of inode 260 in the parent snapshot. So we issue an orphanization operation for inode 260 by emitting a rename operation with a destination path of "o260-6-0" and a source path of "d1/d2" - this source path is the value we stored in the reference earlier at step 2), corresponding to the ->full_path member of the reference, however that path is no longer valid due to the orphanization of the directory inode 259 in step 3). This makes the receiver fail since the path does not exists, it should have been "o259-6-0/d2".
Fix this by recomputing the full path of a reference before emitting an orphanization if we previously orphanized any directory, since that directory could be a parent in the new path. This is a rare scenario so keeping it simple and not checking if that previously orphanized directory is in fact an ancestor of the inode we are trying to orphanize.
A test case for fstests follows soon.
--- fs/btrfs/send.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+)
fs/btrfs/send.c +72 -0
@@ -3813,6 +3813,72 @@ static int update_ref_path(struct send_c }/* +* When processing the new references for an inode we may orphanize an existing +* directory inode because its old name conflicts with one of the new references +* of the current inode. Later, when processing another new reference of our +* inode, we might need to orphanize another inode, but the path we have in the +* reference reflects the pre-orphanization name of the directory we previously +* orphanized. For example: +* +* parent snapshot looks like: +* +* . (ino 256) +* |----- f1 (ino 257) +* |----- f2 (ino 258) +* |----- d1/ (ino 259) +* |----- d2/ (ino 260) +* +* send snapshot looks like: +* +* . (ino 256) +* |----- d1 (ino 258) +* |----- f2/ (ino 259) +* |----- f2_link/ (ino 260) +* | |----- f1 (ino 257) +* | +* |----- d2 (ino 258) +* +* When processing inode 257 we compute the name for inode 259 as "d1", and we +* cache it in the name cache. Later when we start processing inode 258, when +* collecting all its new references we set a full path of "d1/d2" for its new +* reference with name "d2". When we start processing the new references we +* start by processing the new reference with name "d1", and this results in +* orphanizing inode 259, since its old reference causes a conflict. Then we +* move on the next new reference, with name "d2", and we find out we must +* orphanize inode 260, as its old reference conflicts with ours - but for the +* orphanization we use a source path corresponding to the path we stored in the +* new reference, which is "d1/d2" and not "o259-6-0/d2" - this makes the +* receiver fail since the path component "d1/" no longer exists, it was renamed +* to "o259-6-0/" when processing the previous new reference. So in this case we +* must recompute the path in the new reference and use it for the new +* orphanization operation. +*/ +static int refresh_ref_path (struct send_ctx *sctx,struct recorded_ref *ref) +{ +char *name; +int ret; + + name =kmemdup (ref->name, ref->name_len,GFP_KERNEL ); +if (!name) +return -ENOMEM ; + +fs_path_reset (ref->full_path); + ret =get_cur_path (sctx, ref->dir, ref->dir_gen, ref->full_path); +if (ret <0 ) + goto out; + + ret =fs_path_add (ref->full_path, name, ref->name_len); +if (ret <0 ) + goto out; + +/* Update the reference's base name pointer. */ +set_ref_path (ref, ref->full_path); +out: +kfree (name); +return ret; +} + +/* * This does all the move/link/unlink/rmdir magic. */ static int process_recorded_refs (struct send_ctx *sctx,int *pending_move)
@@ -3946,6 +4012,12 @@ static int process_recorded_refs(structstruct name_cache_entry *nce;struct waiting_dir_move *wdm; +if (orphanized_dir) { + ret =refresh_ref_path (sctx, cur); +if (ret <0 ) + goto out; + } + ret =orphanize_inode (sctx, ow_inode, ow_gen, cur->full_path);if (ret <0 )
Greg Kroah-Hartman
maintainerPATCH 229/391 btrfs: use kvzalloc() to allocate clone_roots in btrfs_ioctl_send()
In reply to Greg Kroah-HartmanFrom: Denis Efremov <[email protected]>
commit 8eb2fd00153a3a96a19c62ac9c6d48c2efebe5e8 upstream.
btrfs_ioctl_send() used open-coded kvzalloc implementation earlier. The code was accidentally replaced with kzalloc() call [1]. Restore the original code by using kvzalloc() to allocate sctx->clone_roots.
[1] https://patchwork.kernel.org/patch/9757891/#20529627
--- fs/btrfs/send.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/btrfs/send.c +1 -1
@@ -7300,7 +7300,7 @@ long btrfs_ioctl_send(struct file *mnt_f alloc_size =sizeof (struct clone_root ) * (arg->clone_sources_count +1 ); - sctx->clone_roots =kzalloc (alloc_size,GFP_KERNEL ); + sctx->clone_roots =kvzalloc (alloc_size,GFP_KERNEL );if (!sctx->clone_roots) { ret = -ENOMEM ; goto out;
Greg Kroah-Hartman
maintainerPATCH 230/391 btrfs: tree-checker: fix false alert caused by legacy btrfs root item
In reply to Greg Kroah-HartmanFrom: Qu Wenruo <[email protected]>
commit 1465af12e254a68706e110846f59cf0f09683184 upstream.
Commit 259ee7754b67 ("btrfs: tree-checker: Add ROOT_ITEM check") introduced btrfs root item size check, however btrfs root item has two versions, the legacy one which just ends before generation_v2 member, is smaller than current btrfs root item size.
This caused btrfs kernel to reject valid but old tree root leaves.
Fix this problem by also allowing legacy root item, since kernel can already handle them pretty well and upgrade to newer root item format when needed.
--- fs/btrfs/tree-checker.c | 17 ++++++++++++----- include/uapi/linux/btrfs_tree.h | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 5 deletions(-)
fs/btrfs/tree-checker.c +12 -5
@@ -1035,7 +1035,7 @@ static int check_root_item(struct extent int slot) {struct btrfs_fs_info *fs_info = leaf->fs_info; -struct btrfs_root_item ri; +struct btrfs_root_item ri = {0 };const u64 valid_root_flags =BTRFS_ROOT_SUBVOL_RDONLY |BTRFS_ROOT_SUBVOL_DEAD ;int ret;
@@ -1044,14 +1044,21 @@ static int check_root_item(struct extentif (ret <0 )return ret; -if (btrfs_item_size_nr (leaf, slot) !=sizeof (ri)) { +if (btrfs_item_size_nr (leaf, slot) !=sizeof (ri) && +btrfs_item_size_nr (leaf, slot) !=btrfs_legacy_root_item_size ()) {generic_err (leaf, slot, -"invalid root item size, have %u expect %zu" , -btrfs_item_size_nr (leaf, slot),sizeof (ri)); +"invalid root item size, have %u expect %zu or %u" , +btrfs_item_size_nr (leaf, slot),sizeof (ri), +btrfs_legacy_root_item_size ()); } +/* +* For legacy root item, the members starting at generation_v2 will be +* all filled with 0. +* And since we allow geneartion_v2 as 0, it will still pass the check. +*/ read_extent_buffer (leaf, &ri,btrfs_item_ptr_offset (leaf, slot), -sizeof (ri)); +btrfs_item_size_nr (leaf, slot));/* Generation related */ if (btrfs_root_generation(&ri) >
include/uapi/linux/btrfs_tree.h +14 -0
@@ -4,6 +4,11 @@#include <linux/btrfs.h> #include <linux/types.h> +#ifdef __KERNEL__ +#include <linux/stddef.h> +#else +#include <stddef.h> +#endif /* * This header contains the structure definitions and constants used
@@ -645,6 +650,15 @@ struct btrfs_root_item { } __attribute__ ((__packed__));/* +* Btrfs root item used to be smaller than current size. The old format ends +* at where member generation_v2 is. +*/ +static inline __u32 btrfs_legacy_root_item_size (void ) +{ +return offsetof(struct btrfs_root_item , generation_v2); +} + +/* * this is used for both forward and backward root refs */ struct btrfs_root_ref {
Greg Kroah-Hartman
maintainerPATCH 231/391 btrfs: reschedule when cloning lots of extents
In reply to Greg Kroah-HartmanFrom: Johannes Thumshirn <[email protected]>
commit 6b613cc97f0ace77f92f7bc112b8f6ad3f52baf8 upstream.
We have several occurrences of a soft lockup from fstest's generic/175 testcase, which look more or less like this one:
watchdog: BUG: soft lockup - CPU#0 stuck for 22s! [xfs_io:10030] Kernel panic - not syncing: softlockup: hung tasks CPU: 0 PID: 10030 Comm: xfs_io Tainted: G L 5.9.0-rc5+ #768 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.13.0-0-gf21b5a4-rebuilt.opensuse.org 04/01/2014 Call Trace: <IRQ> dump_stack+0x77/0xa0 panic+0xfa/0x2cb watchdog_timer_fn.cold+0x85/0xa5 ? lockup_detector_update_enable+0x50/0x50 __hrtimer_run_queues+0x99/0x4c0 ? recalibrate_cpu_khz+0x10/0x10 hrtimer_run_queues+0x9f/0xb0 update_process_times+0x28/0x80 tick_handle_periodic+0x1b/0x60 __sysvec_apic_timer_interrupt+0x76/0x210 asm_call_on_stack+0x12/0x20 </IRQ> sysvec_apic_timer_interrupt+0x7f/0x90 asm_sysvec_apic_timer_interrupt+0x12/0x20 RIP: 0010:btrfs_tree_unlock+0x91/0x1a0 [btrfs] RSP: 0018:ffffc90007123a58 EFLAGS: 00000282 RAX: ffff8881cea2fbe0 RBX: ffff8881cea2fbe0 RCX: 0000000000000000 RDX: ffff8881d23fd200 RSI: ffffffff82045220 RDI: ffff8881cea2fba0 RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000032 R10: 0000160000000000 R11: 0000000000001000 R12: 0000000000001000 R13: ffff8882357fd5b0 R14: ffff88816fa76e70 R15: ffff8881cea2fad0 ? btrfs_tree_unlock+0x15b/0x1a0 [btrfs] btrfs_release_path+0x67/0x80 [btrfs] btrfs_insert_replace_extent+0x177/0x2c0 [btrfs] btrfs_replace_file_extents+0x472/0x7c0 [btrfs] btrfs_clone+0x9ba/0xbd0 [btrfs] btrfs_clone_files.isra.0+0xeb/0x140 [btrfs] ? file_update_time+0xcd/0x120 btrfs_remap_file_range+0x322/0x3b0 [btrfs] do_clone_file_range+0xb7/0x1e0 vfs_clone_file_range+0x30/0xa0 ioctl_file_clone+0x8a/0xc0 do_vfs_ioctl+0x5b2/0x6f0 __x64_sys_ioctl+0x37/0xa0 do_syscall_64+0x33/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x7f87977fc247 RSP: 002b:00007ffd51a2f6d8 EFLAGS: 00000206 ORIG_RAX: 0000000000000010 RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f87977fc247 RDX: 00007ffd51a2f710 RSI: 000000004020940d RDI: 0000000000000003 RBP: 0000000000000004 R08: 00007ffd51a79080 R09: 0000000000000000 R10: 00005621f11352f2 R11: 0000000000000206 R12: 0000000000000000 R13: 0000000000000000 R14: 00005621f128b958 R15: 0000000080000000 Kernel Offset: disabled ---[ end Kernel panic - not syncing: softlockup: hung tasks ]---
All of these lockup reports have the call chain btrfs_clone_files() -> btrfs_clone() in common. btrfs_clone_files() calls btrfs_clone() with both source and destination extents locked and loops over the source extent to create the clones.
Conditionally reschedule in the btrfs_clone() loop, to give some time back to other processes.
--- fs/btrfs/reflink.c | 2 ++ 1 file changed, 2 insertions(+)
fs/btrfs/reflink.c +2 -0
@@ -520,6 +520,8 @@ process_slot: ret = -EINTR ; goto out; } + +cond_resched (); } ret =0 ;
Greg Kroah-Hartman
maintainerPATCH 232/391 btrfs: cleanup cow block on error
In reply to Greg Kroah-HartmanFrom: Josef Bacik <[email protected]>
commit 572c83acdcdafeb04e70aa46be1fa539310be20c upstream.
In fstest btrfs/064 a transaction abort in __btrfs_cow_block could lead to a system lockup. It gets stuck trying to write back inodes, and the write back thread was trying to lock an extent buffer:
$ cat /proc/2143497/stack [<0>] __btrfs_tree_lock+0x108/0x250 [<0>] lock_extent_buffer_for_io+0x35e/0x3a0 [<0>] btree_write_cache_pages+0x15a/0x3b0 [<0>] do_writepages+0x28/0xb0 [<0>] __writeback_single_inode+0x54/0x5c0 [<0>] writeback_sb_inodes+0x1e8/0x510 [<0>] wb_writeback+0xcc/0x440 [<0>] wb_workfn+0xd7/0x650 [<0>] process_one_work+0x236/0x560 [<0>] worker_thread+0x55/0x3c0 [<0>] kthread+0x13a/0x150 [<0>] ret_from_fork+0x1f/0x30
This is because we got an error while COWing a block, specifically here
if (test_bit(BTRFS_ROOT_SHAREABLE, &root->state)) {
ret = btrfs_reloc_cow_block(trans, root, buf, cow);
if (ret) {
btrfs_abort_transaction(trans, ret);
return ret;
}
}[16402.241552] BTRFS: Transaction aborted (error -2) [16402.242362] WARNING: CPU: 1 PID: 2563188 at fs/btrfs/ctree.c:1074 __btrfs_cow_block+0x376/0x540 [16402.249469] CPU: 1 PID: 2563188 Comm: fsstress Not tainted 5.9.0-rc6+ #8 [16402.249936] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-2.fc32 04/01/2014 [16402.250525] RIP: 0010:__btrfs_cow_block+0x376/0x540 [16402.252417] RSP: 0018:ffff9cca40e578b0 EFLAGS: 00010282 [16402.252787] RAX: 0000000000000025 RBX: 0000000000000002 RCX: ffff9132bbd19388 [16402.253278] RDX: 00000000ffffffd8 RSI: 0000000000000027 RDI: ffff9132bbd19380 [16402.254063] RBP: ffff9132b41a49c0 R08: 0000000000000000 R09: 0000000000000000 [16402.254887] R10: 0000000000000000 R11: ffff91324758b080 R12: ffff91326ef17ce0 [16402.255694] R13: ffff91325fc0f000 R14: ffff91326ef176b0 R15: ffff9132815e2000 [16402.256321] FS: 00007f542c6d7b80(0000) GS:ffff9132bbd00000(0000) knlGS:0000000000000000 [16402.256973] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [16402.257374] CR2: 00007f127b83f250 CR3: 0000000133480002 CR4: 0000000000370ee0 [16402.257867] Call Trace: [16402.258072] btrfs_cow_block+0x109/0x230 [16402.258356] btrfs_search_slot+0x530/0x9d0 [16402.258655] btrfs_lookup_file_extent+0x37/0x40 [16402.259155] __btrfs_drop_extents+0x13c/0xd60 [16402.259628] ? btrfs_block_rsv_migrate+0x4f/0xb0 [16402.259949] btrfs_replace_file_extents+0x190/0x820 [16402.260873] btrfs_clone+0x9ae/0xc00 [16402.261139] btrfs_extent_same_range+0x66/0x90 [16402.261771] btrfs_remap_file_range+0x353/0x3b1 [16402.262333] vfs_dedupe_file_range_one.part.0+0xd5/0x140 [16402.262821] vfs_dedupe_file_range+0x189/0x220 [16402.263150] do_vfs_ioctl+0x552/0x700 [16402.263662] __x64_sys_ioctl+0x62/0xb0 [16402.264023] do_syscall_64+0x33/0x40 [16402.264364] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [16402.264862] RIP: 0033:0x7f542c7d15cb [16402.266901] RSP: 002b:00007ffd35944ea8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 [16402.267627] RAX: ffffffffffffffda RBX: 00000000009d1968 RCX: 00007f542c7d15cb [16402.268298] RDX: 00000000009d2490 RSI: 00000000c0189436 RDI: 0000000000000003 [16402.268958] RBP: 00000000009d2520 R08: 0000000000000036 R09: 00000000009d2e64 [16402.269726] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000002 [16402.270659] R13: 000000000001f000 R14: 00000000009d1970 R15: 00000000009d2e80 [16402.271498] irq event stamp: 0 [16402.271846] hardirqs last enabled at (0): [<0000000000000000>] 0x0 [16402.272497] hardirqs last disabled at (0): [<ffffffff910dbf59>] copy_process+0x6b9/0x1ba0 [16402.273343] softirqs last enabled at (0): [<ffffffff910dbf59>] copy_process+0x6b9/0x1ba0 [16402.273905] softirqs last disabled at (0): [<0000000000000000>] 0x0 [16402.274338] ---[ end trace 737874a5a41a8236 ]--- [16402.274669] BTRFS: error (device dm-9) in __btrfs_cow_block:1074: errno=-2 No such entry [16402.276179] BTRFS info (device dm-9): forced readonly [16402.277046] BTRFS: error (device dm-9) in btrfs_replace_file_extents:2723: errno=-2 No such entry [16402.278744] BTRFS: error (device dm-9) in __btrfs_cow_block:1074: errno=-2 No such entry [16402.279968] BTRFS: error (device dm-9) in __btrfs_cow_block:1074: errno=-2 No such entry [16402.280582] BTRFS info (device dm-9): balance: ended with status: -30
The problem here is that as soon as we allocate the new block it is locked and marked dirty in the btree inode. This means that we could attempt to writeback this block and need to lock the extent buffer. However we're not unlocking it here and thus we deadlock.
Fix this by unlocking the cow block if we have any errors inside of __btrfs_cow_block, and also free it so we do not leak it.
--- fs/btrfs/ctree.c | 6 ++++++ 1 file changed, 6 insertions(+)
fs/btrfs/ctree.c +6 -0
@@ -1061,6 +1061,8 @@ static noinline int __btrfs_cow_block(st ret =update_ref_for_cow (trans, root, buf, cow, &last_ref);if (ret) { +btrfs_tree_unlock (cow); +free_extent_buffer (cow);btrfs_abort_transaction (trans, ret);return ret; }
@@ -1068,6 +1070,8 @@ static noinline int __btrfs_cow_block(stif (test_bit (BTRFS_ROOT_SHAREABLE , &root->state)) { ret =btrfs_reloc_cow_block (trans, root, buf, cow);if (ret) { +btrfs_tree_unlock (cow); +free_extent_buffer (cow);btrfs_abort_transaction (trans, ret);return ret; }
@@ -1100,6 +1104,8 @@ static noinline int __btrfs_cow_block(stif (last_ref) { ret =tree_mod_log_free_eb (buf);if (ret) { +btrfs_tree_unlock (cow); +free_extent_buffer (cow);btrfs_abort_transaction (trans, ret);return ret; }
Greg Kroah-Hartman
maintainerPATCH 233/391 btrfs: skip devices without magic signature when mounting
In reply to Greg Kroah-HartmanFrom: Anand Jain <[email protected]>
commit 96c2e067ed3e3e004580a643c76f58729206b829 upstream.
Many things can happen after the device is scanned and before the device is mounted. One such thing is losing the BTRFS_MAGIC on the device. If it happens we still won't free that device from the memory and cause the userland confusion.
For example: As the BTRFS_IOC_DEV_INFO still carries the device path which does not have the BTRFS_MAGIC, 'btrfs fi show' still lists device which does not belong to the filesystem anymore:
$ mkfs.btrfs -fq -draid1 -mraid1 /dev/sda /dev/sdb $ wipefs -a /dev/sdb # /dev/sdb does not contain magic signature $ mount -o degraded /dev/sda /btrfs $ btrfs fi show -m Label: none uuid: 470ec6fb-646b-4464-b3cb-df1b26c527bd Total devices 2 FS bytes used 128.00KiB devid 1 size 3.00GiB used 571.19MiB path /dev/sda devid 2 size 3.00GiB used 571.19MiB path /dev/sdb
We need to distinguish the missing signature and invalid superblock, so add a specific error code ENODATA for that. This also fixes failure of fstest btrfs/198.
--- fs/btrfs/disk-io.c | 8 ++++++-- fs/btrfs/volumes.c | 18 ++++++++++++------ 2 files changed, 18 insertions(+), 8 deletions(-)
fs/btrfs/disk-io.c +6 -2
@@ -3482,8 +3482,12 @@ struct btrfs_super_block *btrfs_read_devreturn ERR_CAST (page); super =page_address (page); -if (btrfs_super_bytenr (super) != bytenr || -btrfs_super_magic (super) !=BTRFS_MAGIC ) { +if (btrfs_super_magic (super) !=BTRFS_MAGIC ) { +btrfs_release_disk_super (super); +return ERR_PTR (-ENODATA ); + } + +if (btrfs_super_bytenr (super) != bytenr) {btrfs_release_disk_super (super);return ERR_PTR (-EINVAL ); }
fs/btrfs/volumes.c +12 -6
@@ -1200,17 +1200,23 @@ static int open_fs_devices(struct btrfs_ {struct btrfs_device *device;struct btrfs_device *latest_dev =NULL ; +struct btrfs_device *tmp_device; flags |=FMODE_EXCL ; -list_for_each_entry (device, &fs_devices->devices, dev_list) { -/* Just open everything we can; ignore failures here */ -if (btrfs_open_one_device (fs_devices, device, flags, holder)) -continue ; +list_for_each_entry_safe (device, tmp_device, &fs_devices->devices, + dev_list) { +int ret; -if (!latest_dev || - device->generation > latest_dev->generation) + ret =btrfs_open_one_device (fs_devices, device, flags, holder); +if (ret ==0 && + (!latest_dev || device->generation > latest_dev->generation)) { latest_dev = device; + }else if (ret == -ENODATA ) { + fs_devices->num_devices--; +list_del (&device->dev_list); +btrfs_free_device (device); + } }if (fs_devices->open_devices ==0 )return -EINVAL ;
Greg Kroah-Hartman
maintainerPATCH 234/391 btrfs: tree-checker: validate number of chunk stripes and parity
In reply to Greg Kroah-HartmanFrom: Daniel Xu <[email protected]>
commit 85d07fbe09efd1c529ff3e025e2f0d2c6c96a1b7 upstream.
If there's no parity and num_stripes < ncopies, a crafted image can trigger a division by zero in calc_stripe_length().
The image was generated through fuzzing.
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=209587
--- fs/btrfs/tree-checker.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
fs/btrfs/tree-checker.c +18 -0
@@ -760,18 +760,36 @@ int btrfs_check_chunk_valid(struct extenu64 type;u64 features;bool mixed = false; +int raid_index; +int nparity; +int ncopies; length =btrfs_chunk_length (leaf, chunk); stripe_len =btrfs_chunk_stripe_len (leaf, chunk); num_stripes =btrfs_chunk_num_stripes (leaf, chunk); sub_stripes =btrfs_chunk_sub_stripes (leaf, chunk); type =btrfs_chunk_type (leaf, chunk); + raid_index =btrfs_bg_flags_to_raid_index (type); + ncopies = btrfs_raid_array[raid_index].ncopies; + nparity = btrfs_raid_array[raid_index].nparity;if (!num_stripes) {chunk_err (leaf, chunk, logical,"invalid chunk num_stripes, have %u" , num_stripes);return -EUCLEAN ; } +if (num_stripes < ncopies) { +chunk_err (leaf, chunk, logical, +"invalid chunk num_stripes < ncopies, have %u < %d" , + num_stripes, ncopies); +return -EUCLEAN ; + } +if (nparity && num_stripes == nparity) { +chunk_err (leaf, chunk, logical, +"invalid chunk num_stripes == nparity, have %u == %d" , + num_stripes, nparity); +return -EUCLEAN ; + }if (!IS_ALIGNED (logical, fs_info->sectorsize)) { chunk_err(leaf, chunk, logical, "invalid chunk logical, have %llu should aligned to %u",
Greg Kroah-Hartman
maintainerPATCH 235/391 btrfs: fix use-after-free on readahead extent after failure to create it
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
commit 83bc1560e02e25c6439341352024ebe8488f4fbd upstream.
If we fail to find suitable zones for a new readahead extent, we end up leaving a stale pointer in the global readahead extents radix tree (fs_info->reada_tree), which can trigger the following trace later on:
[13367.696354] BUG: kernel NULL pointer dereference, address: 00000000000000b0 [13367.696802] #PF: supervisor read access in kernel mode [13367.697249] #PF: error_code(0x0000) - not-present page [13367.697721] PGD 0 P4D 0 [13367.698171] Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC PTI [13367.698632] CPU: 6 PID: 851214 Comm: btrfs Tainted: G W 5.9.0-rc6-btrfs-next-69 #1 [13367.699100] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 [13367.700069] RIP: 0010:__lock_acquire+0x20a/0x3970 [13367.700562] Code: ff 1f 0f b7 c0 48 0f (...) [13367.701609] RSP: 0018:ffffb14448f57790 EFLAGS: 00010046 [13367.702140] RAX: 0000000000000000 RBX: 29b935140c15e8cf RCX: 0000000000000000 [13367.702698] RDX: 0000000000000002 RSI: ffffffffb3d66bd0 RDI: 0000000000000046 [13367.703240] RBP: ffff8a52ba8ac040 R08: 00000c2866ad9288 R09: 0000000000000001 [13367.703783] R10: 0000000000000001 R11: 00000000b66d9b53 R12: ffff8a52ba8ac9b0 [13367.704330] R13: 0000000000000000 R14: ffff8a532b6333e8 R15: 0000000000000000 [13367.704880] FS: 00007fe1df6b5700(0000) GS:ffff8a5376600000(0000) knlGS:0000000000000000 [13367.705438] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [13367.705995] CR2: 00000000000000b0 CR3: 000000022cca8004 CR4: 00000000003706e0 [13367.706565] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [13367.707127] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [13367.707686] Call Trace: [13367.708246] ? ___slab_alloc+0x395/0x740 [13367.708820] ? reada_add_block+0xae/0xee0 [btrfs] [13367.709383] lock_acquire+0xb1/0x480 [13367.709955] ? reada_add_block+0xe0/0xee0 [btrfs] [13367.710537] ? reada_add_block+0xae/0xee0 [btrfs] [13367.711097] ? rcu_read_lock_sched_held+0x5d/0x90 [13367.711659] ? kmem_cache_alloc_trace+0x8d2/0x990 [13367.712221] ? lock_acquired+0x33b/0x470 [13367.712784] _raw_spin_lock+0x34/0x80 [13367.713356] ? reada_add_block+0xe0/0xee0 [btrfs] [13367.713966] reada_add_block+0xe0/0xee0 [btrfs] [13367.714529] ? btrfs_root_node+0x15/0x1f0 [btrfs] [13367.715077] btrfs_reada_add+0x117/0x170 [btrfs] [13367.715620] scrub_stripe+0x21e/0x10d0 [btrfs] [13367.716141] ? kvm_sched_clock_read+0x5/0x10 [13367.716657] ? __lock_acquire+0x41e/0x3970 [13367.717184] ? scrub_chunk+0x60/0x140 [btrfs] [13367.717697] ? find_held_lock+0x32/0x90 [13367.718254] ? scrub_chunk+0x60/0x140 [btrfs] [13367.718773] ? lock_acquired+0x33b/0x470 [13367.719278] ? scrub_chunk+0xcd/0x140 [btrfs] [13367.719786] scrub_chunk+0xcd/0x140 [btrfs] [13367.720291] scrub_enumerate_chunks+0x270/0x5c0 [btrfs] [13367.720787] ? finish_wait+0x90/0x90 [13367.721281] btrfs_scrub_dev+0x1ee/0x620 [btrfs] [13367.721762] ? rcu_read_lock_any_held+0x8e/0xb0 [13367.722235] ? preempt_count_add+0x49/0xa0 [13367.722710] ? __sb_start_write+0x19b/0x290 [13367.723192] btrfs_ioctl+0x7f5/0x36f0 [btrfs] [13367.723660] ? __fget_files+0x101/0x1d0 [13367.724118] ? find_held_lock+0x32/0x90 [13367.724559] ? __fget_files+0x101/0x1d0 [13367.724982] ? __x64_sys_ioctl+0x83/0xb0 [13367.725399] __x64_sys_ioctl+0x83/0xb0 [13367.725802] do_syscall_64+0x33/0x80 [13367.726188] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [13367.726574] RIP: 0033:0x7fe1df7add87 [13367.726948] Code: 00 00 00 48 8b 05 09 91 (...) [13367.727763] RSP: 002b:00007fe1df6b4d48 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 [13367.728179] RAX: ffffffffffffffda RBX: 000055ce1fb596a0 RCX: 00007fe1df7add87 [13367.728604] RDX: 000055ce1fb596a0 RSI: 00000000c400941b RDI: 0000000000000003 [13367.729021] RBP: 0000000000000000 R08: 00007fe1df6b5700 R09: 0000000000000000 [13367.729431] R10: 00007fe1df6b5700 R11: 0000000000000246 R12: 00007ffd922b07de [13367.729842] R13: 00007ffd922b07df R14: 00007fe1df6b4e40 R15: 0000000000802000 [13367.730275] Modules linked in: btrfs blake2b_generic xor (...) [13367.732638] CR2: 00000000000000b0 [13367.733166] ---[ end trace d298b6805556acd9 ]---
What happens is the following:
1) At reada_find_extent() we don't find any existing readahead extent for the metadata extent starting at logical address X;
2) So we proceed to create a new one. We then call btrfs_map_block() to get information about which stripes contain extent X;
3) After that we iterate over the stripes and create only one zone for the readahead extent - only one because reada_find_zone() returned NULL for all iterations except for one, either because a memory allocation failed or it couldn't find the block group of the extent (it may have just been deleted);
4) We then add the new readahead extent to the readahead extents radix tree at fs_info->reada_tree;
5) Then we iterate over each zone of the new readahead extent, and find that the device used for that zone no longer exists, because it was removed or it was the source device of a device replace operation. Since this left 'have_zone' set to 0, after finishing the loop we jump to the 'error' label, call kfree() on the new readahead extent and return without removing it from the radix tree at fs_info->reada_tree;
6) Any future call to reada_find_extent() for the logical address X will find the stale pointer in the readahead extents radix tree, increment its reference counter, which can trigger the use-after-free right away or return it to the caller reada_add_block() that results in the use-after-free of the example trace above.
So fix this by making sure we delete the readahead extent from the radix tree if we fail to setup zones for it (when 'have_zone = 0').
--- fs/btrfs/reada.c | 2 ++ 1 file changed, 2 insertions(+)
fs/btrfs/reada.c +2 -0
@@ -445,6 +445,8 @@ static struct reada_extent *reada_find_e } have_zone =1 ; } +if (!have_zone) +radix_tree_delete (&fs_info->reada_tree, index);spin_unlock (&fs_info->reada_lock);up_read (&fs_info->dev_replace.rwsem);
Greg Kroah-Hartman
maintainerPATCH 236/391 btrfs: fix readahead hang and use-after-free after removing a device
In reply to Greg Kroah-HartmanFrom: Filipe Manana <[email protected]>
commit 66d204a16c94f24ad08290a7663ab67e7fc04e82 upstream.
Very sporadically I had test case btrfs/069 from fstests hanging (for years, it is not a recent regression), with the following traces in dmesg/syslog:
[162301.160628] BTRFS info (device sdc): dev_replace from /dev/sdd (devid 2) to /dev/sdg started
[162301.181196] BTRFS info (device sdc): scrub: finished on devid 4 with status: 0
[162301.287162] BTRFS info (device sdc): dev_replace from /dev/sdd (devid 2) to /dev/sdg finished
[162513.513792] INFO: task btrfs-transacti:1356167 blocked for more than 120 seconds.
[162513.514318] Not tainted 5.9.0-rc6-btrfs-next-69 #1
[162513.514522] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[162513.514747] task:btrfs-transacti state:D stack: 0 pid:1356167 ppid: 2 flags:0x00004000
[162513.514751] Call Trace:
[162513.514761] __schedule+0x5ce/0xd00
[162513.514765] ? _raw_spin_unlock_irqrestore+0x3c/0x60
[162513.514771] schedule+0x46/0xf0
[162513.514844] wait_current_trans+0xde/0x140 [btrfs]
[162513.514850] ? finish_wait+0x90/0x90
[162513.514864] start_transaction+0x37c/0x5f0 [btrfs]
[162513.514879] transaction_kthread+0xa4/0x170 [btrfs]
[162513.514891] ? btrfs_cleanup_transaction+0x660/0x660 [btrfs]
[162513.514894] kthread+0x153/0x170
[162513.514897] ? kthread_stop+0x2c0/0x2c0
[162513.514902] ret_from_fork+0x22/0x30
[162513.514916] INFO: task fsstress:1356184 blocked for more than 120 seconds.
[162513.515192] Not tainted 5.9.0-rc6-btrfs-next-69 #1
[162513.515431] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[162513.515680] task:fsstress state:D stack: 0 pid:1356184 ppid:1356177 flags:0x00004000
[162513.515682] Call Trace:
[162513.515688] __schedule+0x5ce/0xd00
[162513.515691] ? _raw_spin_unlock_irqrestore+0x3c/0x60
[162513.515697] schedule+0x46/0xf0
[162513.515712] wait_current_trans+0xde/0x140 [btrfs]
[162513.515716] ? finish_wait+0x90/0x90
[162513.515729] start_transaction+0x37c/0x5f0 [btrfs]
[162513.515743] btrfs_attach_transaction_barrier+0x1f/0x50 [btrfs]
[162513.515753] btrfs_sync_fs+0x61/0x1c0 [btrfs]
[162513.515758] ? __ia32_sys_fdatasync+0x20/0x20
[162513.515761] iterate_supers+0x87/0xf0
[162513.515765] ksys_sync+0x60/0xb0
[162513.515768] __do_sys_sync+0xa/0x10
[162513.515771] do_syscall_64+0x33/0x80
[162513.515774] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[162513.515781] RIP: 0033:0x7f5238f50bd7
[162513.515782] Code: Bad RIP value.
[162513.515784] RSP: 002b:00007fff67b978e8 EFLAGS: 00000206 ORIG_RAX: 00000000000000a2
[162513.515786] RAX: ffffffffffffffda RBX: 000055b1fad2c560 RCX: 00007f5238f50bd7
[162513.515788] RDX: 00000000ffffffff RSI: 000000000daf0e74 RDI: 000000000000003a
[162513.515789] RBP: 0000000000000032 R08: 000000000000000a R09: 00007f5239019be0
[162513.515791] R10: fffffffffffff24f R11: 0000000000000206 R12: 000000000000003a
[162513.515792] R13: 00007fff67b97950 R14: 00007fff67b97906 R15: 000055b1fad1a340
[162513.515804] INFO: task fsstress:1356185 blocked for more than 120 seconds.
[162513.516064] Not tainted 5.9.0-rc6-btrfs-next-69 #1
[162513.516329] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[162513.516617] task:fsstress state:D stack: 0 pid:1356185 ppid:1356177 flags:0x00000000
[162513.516620] Call Trace:
[162513.516625] __schedule+0x5ce/0xd00
[162513.516628] ? _raw_spin_unlock_irqrestore+0x3c/0x60
[162513.516634] schedule+0x46/0xf0
[162513.516647] wait_current_trans+0xde/0x140 [btrfs]
[162513.516650] ? finish_wait+0x90/0x90
[162513.516662] start_transaction+0x4d7/0x5f0 [btrfs]
[162513.516679] btrfs_setxattr_trans+0x3c/0x100 [btrfs]
[162513.516686] __vfs_setxattr+0x66/0x80
[162513.516691] __vfs_setxattr_noperm+0x70/0x200
[162513.516697] vfs_setxattr+0x6b/0x120
[162513.516703] setxattr+0x125/0x240
[162513.516709] ? lock_acquire+0xb1/0x480
[162513.516712] ? mnt_want_write+0x20/0x50
[162513.516721] ? rcu_read_lock_any_held+0x8e/0xb0
[162513.516723] ? preempt_count_add+0x49/0xa0
[162513.516725] ? __sb_start_write+0x19b/0x290
[162513.516727] ? preempt_count_add+0x49/0xa0
[162513.516732] path_setxattr+0xba/0xd0
[162513.516739] __x64_sys_setxattr+0x27/0x30
[162513.516741] do_syscall_64+0x33/0x80
[162513.516743] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[162513.516745] RIP: 0033:0x7f5238f56d5a
[162513.516746] Code: Bad RIP value.
[162513.516748] RSP: 002b:00007fff67b97868 EFLAGS: 00000202 ORIG_RAX: 00000000000000bc
[162513.516750] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007f5238f56d5a
[162513.516751] RDX: 000055b1fbb0d5a0 RSI: 00007fff67b978a0 RDI: 000055b1fbb0d470
[162513.516753] RBP: 000055b1fbb0d5a0 R08: 0000000000000001 R09: 00007fff67b97700
[162513.516754] R10: 0000000000000004 R11: 0000000000000202 R12: 0000000000000004
[162513.516756] R13: 0000000000000024 R14: 0000000000000001 R15: 00007fff67b978a0
[162513.516767] INFO: task fsstress:1356196 blocked for more than 120 seconds.
[162513.517064] Not tainted 5.9.0-rc6-btrfs-next-69 #1
[162513.517365] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[162513.517763] task:fsstress state:D stack: 0 pid:1356196 ppid:1356177 flags:0x00004000
[162513.517780] Call Trace:
[162513.517786] __schedule+0x5ce/0xd00
[162513.517789] ? _raw_spin_unlock_irqrestore+0x3c/0x60
[162513.517796] schedule+0x46/0xf0
[162513.517810] wait_current_trans+0xde/0x140 [btrfs]
[162513.517814] ? finish_wait+0x90/0x90
[162513.517829] start_transaction+0x37c/0x5f0 [btrfs]
[162513.517845] btrfs_attach_transaction_barrier+0x1f/0x50 [btrfs]
[162513.517857] btrfs_sync_fs+0x61/0x1c0 [btrfs]
[162513.517862] ? __ia32_sys_fdatasync+0x20/0x20
[162513.517865] iterate_supers+0x87/0xf0
[162513.517869] ksys_sync+0x60/0xb0
[162513.517872] __do_sys_sync+0xa/0x10
[162513.517875] do_syscall_64+0x33/0x80
[162513.517878] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[162513.517881] RIP: 0033:0x7f5238f50bd7
[162513.517883] Code: Bad RIP value.
[162513.517885] RSP: 002b:00007fff67b978e8 EFLAGS: 00000206 ORIG_RAX: 00000000000000a2
[162513.517887] RAX: ffffffffffffffda RBX: 000055b1fad2c560 RCX: 00007f5238f50bd7
[162513.517889] RDX: 0000000000000000 RSI: 000000007660add2 RDI: 0000000000000053
[162513.517891] RBP: 0000000000000032 R08: 0000000000000067 R09: 00007f5239019be0
[162513.517893] R10: fffffffffffff24f R11: 0000000000000206 R12: 0000000000000053
[162513.517895] R13: 00007fff67b97950 R14: 00007fff67b97906 R15: 000055b1fad1a340
[162513.517908] INFO: task fsstress:1356197 blocked for more than 120 seconds.
[162513.518298] Not tainted 5.9.0-rc6-btrfs-next-69 #1
[162513.518672] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[162513.519157] task:fsstress state:D stack: 0 pid:1356197 ppid:1356177 flags:0x00000000
[162513.519160] Call Trace:
[162513.519165] __schedule+0x5ce/0xd00
[162513.519168] ? _raw_spin_unlock_irqrestore+0x3c/0x60
[162513.519174] schedule+0x46/0xf0
[162513.519190] wait_current_trans+0xde/0x140 [btrfs]
[162513.519193] ? finish_wait+0x90/0x90
[162513.519206] start_transaction+0x4d7/0x5f0 [btrfs]
[162513.519222] btrfs_create+0x57/0x200 [btrfs]
[162513.519230] lookup_open+0x522/0x650
[162513.519246] path_openat+0x2b8/0xa50
[162513.519270] do_filp_open+0x91/0x100
[162513.519275] ? find_held_lock+0x32/0x90
[162513.519280] ? lock_acquired+0x33b/0x470
[162513.519285] ? do_raw_spin_unlock+0x4b/0xc0
[162513.519287] ? _raw_spin_unlock+0x29/0x40
[162513.519295] do_sys_openat2+0x20d/0x2d0
[162513.519300] do_sys_open+0x44/0x80
[162513.519304] do_syscall_64+0x33/0x80
[162513.519307] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[162513.519309] RIP: 0033:0x7f5238f4a903
[162513.519310] Code: Bad RIP value.
[162513.519312] RSP: 002b:00007fff67b97758 EFLAGS: 00000246 ORIG_RAX: 0000000000000055
[162513.519314] RAX: ffffffffffffffda RBX: 00000000ffffffff RCX: 00007f5238f4a903
[162513.519316] RDX: 0000000000000000 RSI: 00000000000001b6 RDI: 000055b1fbb0d470
[162513.519317] RBP: 00007fff67b978c0 R08: 0000000000000001 R09: 0000000000000002
[162513.519319] R10: 00007fff67b974f7 R11: 0000000000000246 R12: 0000000000000013
[162513.519320] R13: 00000000000001b6 R14: 00007fff67b97906 R15: 000055b1fad1c620
[162513.519332] INFO: task btrfs:1356211 blocked for more than 120 seconds.
[162513.519727] Not tainted 5.9.0-rc6-btrfs-next-69 #1
[162513.520115] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[162513.520508] task:btrfs state:D stack: 0 pid:1356211 ppid:1356178 flags:0x00004002
[162513.520511] Call Trace:
[162513.520516] __schedule+0x5ce/0xd00
[162513.520519] ? _raw_spin_unlock_irqrestore+0x3c/0x60
[162513.520525] schedule+0x46/0xf0
[162513.520544] btrfs_scrub_pause+0x11f/0x180 [btrfs]
[162513.520548] ? finish_wait+0x90/0x90
[162513.520562] btrfs_commit_transaction+0x45a/0xc30 [btrfs]
[162513.520574] ? start_transaction+0xe0/0x5f0 [btrfs]
[162513.520596] btrfs_dev_replace_finishing+0x6d8/0x711 [btrfs]
[162513.520619] btrfs_dev_replace_by_ioctl.cold+0x1cc/0x1fd [btrfs]
[162513.520639] btrfs_ioctl+0x2a25/0x36f0 [btrfs]
[162513.520643] ? do_sigaction+0xf3/0x240
[162513.520645] ? find_held_lock+0x32/0x90
[162513.520648] ? do_sigaction+0xf3/0x240
[162513.520651] ? lock_acquired+0x33b/0x470
[162513.520655] ? _raw_spin_unlock_irq+0x24/0x50
[162513.520657] ? lockdep_hardirqs_on+0x7d/0x100
[162513.520660] ? _raw_spin_unlock_irq+0x35/0x50
[162513.520662] ? do_sigaction+0xf3/0x240
[162513.520671] ? __x64_sys_ioctl+0x83/0xb0
[162513.520672] __x64_sys_ioctl+0x83/0xb0
[162513.520677] do_syscall_64+0x33/0x80
[162513.520679] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[162513.520681] RIP: 0033:0x7fc3cd307d87
[162513.520682] Code: Bad RIP value.
[162513.520684] RSP: 002b:00007ffe30a56bb8 EFLAGS: 00000202 ORIG_RAX: 0000000000000010
[162513.520686] RAX: ffffffffffffffda RBX: 0000000000000004 RCX: 00007fc3cd307d87
[162513.520687] RDX: 00007ffe30a57a30 RSI: 00000000ca289435 RDI: 0000000000000003
[162513.520689] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
[162513.520690] R10: 0000000000000008 R11: 0000000000000202 R12: 0000000000000003
[162513.520692] R13: 0000557323a212e0 R14: 00007ffe30a5a520 R15: 0000000000000001
[162513.520703]
Showing all locks held in the system:
[162513.520712] 1 lock held by khungtaskd/54:
[162513.520713] #0: ffffffffb40a91a0 (rcu_read_lock){....}-{1:2}, at: debug_show_all_locks+0x15/0x197
[162513.520728] 1 lock held by in:imklog/596:
[162513.520729] #0: ffff8f3f0d781400 (&f->f_pos_lock){+.+.}-{3:3}, at: __fdget_pos+0x4d/0x60
[162513.520782] 1 lock held by btrfs-transacti/1356167:
[162513.520784] #0: ffff8f3d810cc848 (&fs_info->transaction_kthread_mutex){+.+.}-{3:3}, at: transaction_kthread+0x4a/0x170 [btrfs]
[162513.520798] 1 lock held by btrfs/1356190:
[162513.520800] #0: ffff8f3d57644470 (sb_writers#15){.+.+}-{0:0}, at: mnt_want_write_file+0x22/0x60
[162513.520805] 1 lock held by fsstress/1356184:
[162513.520806] #0: ffff8f3d576440e8 (&type->s_umount_key#62){++++}-{3:3}, at: iterate_supers+0x6f/0xf0
[162513.520811] 3 locks held by fsstress/1356185:
[162513.520812] #0: ffff8f3d57644470 (sb_writers#15){.+.+}-{0:0}, at: mnt_want_write+0x20/0x50
[162513.520815] #1: ffff8f3d80a650b8 (&type->i_mutex_dir_key#10){++++}-{3:3}, at: vfs_setxattr+0x50/0x120
[162513.520820] #2: ffff8f3d57644690 (sb_internal#2){.+.+}-{0:0}, at: start_transaction+0x40e/0x5f0 [btrfs]
[162513.520833] 1 lock held by fsstress/1356196:
[162513.520834] #0: ffff8f3d576440e8 (&type->s_umount_key#62){++++}-{3:3}, at: iterate_supers+0x6f/0xf0
[162513.520838] 3 locks held by fsstress/1356197:
[162513.520839] #0: ffff8f3d57644470 (sb_writers#15){.+.+}-{0:0}, at: mnt_want_write+0x20/0x50
[162513.520843] #1: ffff8f3d506465e8 (&type->i_mutex_dir_key#10){++++}-{3:3}, at: path_openat+0x2a7/0xa50
[162513.520846] #2: ffff8f3d57644690 (sb_internal#2){.+.+}-{0:0}, at: start_transaction+0x40e/0x5f0 [btrfs]
[162513.520858] 2 locks held by btrfs/1356211:
[162513.520859] #0: ffff8f3d810cde30 (&fs_info->dev_replace.lock_finishing_cancel_unmount){+.+.}-{3:3}, at: btrfs_dev_replace_finishing+0x52/0x711 [btrfs]
[162513.520877] #1: ffff8f3d57644690 (sb_internal#2){.+.+}-{0:0}, at: start_transaction+0x40e/0x5f0 [btrfs]This was weird because the stack traces show that a transaction commit, triggered by a device replace operation, is blocking trying to pause any running scrubs but there are no stack traces of blocked tasks doing a scrub.
After poking around with drgn, I noticed there was a scrub task that was constantly running and blocking for shorts periods of time:
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
t =
find_task(prog, 1356190)prog.stack_trace(t)
#0 __schedule+0x5ce/0xcfc #1 schedule+0x46/0xe4 #2 schedule_timeout+0x1df/0x475 #3 btrfs_reada_wait+0xda/0x132 #4 scrub_stripe+0x2a8/0x112f #5 scrub_chunk+0xcd/0x134 #6 scrub_enumerate_chunks+0x29e/0x5ee #7 btrfs_scrub_dev+0x2d5/0x91b #8 btrfs_ioctl+0x7f5/0x36e7 #9 __x64_sys_ioctl+0x83/0xb0
#10 do_syscall_64+0x33/0x77
#11 entry_SYSCALL_64+0x7c/0x156
Which corresponds to:
int btrfs_reada_wait(void *handle)
{
struct reada_control *rc = handle;
struct btrfs_fs_info *fs_info = rc->fs_info;
while (atomic_read(&rc->elems)) {
if (!atomic_read(&fs_info->reada_works_cnt))
reada_start_machine(fs_info);
wait_event_timeout(rc->wait, atomic_read(&rc->elems) == 0,
(HZ + 9) / 10);
}(...)
So the counter "rc->elems" was set to 1 and never decreased to 0, causing the scrub task to loop forever in that function. Then I used the following script for drgn to check the readahead requests:
$ cat dump_reada.py
import sys
import drgn
from drgn import NULL, Object, cast, container_of, execscript, \
reinterpret, sizeof
from drgn.helpers.linux import * mnt_path = b"/home/fdmanana/btrfs-tests/scratch_1"
mnt = None
for mnt in for_each_mount(prog, dst = mnt_path):
pass
if mnt is None:
sys.stderr.write(f'Error: mount point {mnt_path} not found\n') sys.exit(1)
fs_info = cast('struct btrfs_fs_info *', mnt.mnt.mnt_sb.s_fs_info)
def dump_re(re):
nzones = re.nzones.value_()
print(f're at {hex(re.value_())}')
print(f'\t logical {re.logical.value_()}') print(f'\t refcnt {re.refcnt.value_()}') print(f'\t nzones {nzones}')
for i in range(nzones):
dev = re.zones[i].device
name = dev.name.str.string_()
print(f'\t\t dev id {dev.devid.value_()} name {name}')
print()
for _, e in radix_tree_for_each(fs_info.reada_tree):
re = cast('struct reada_extent *', e) dump_re(re)
$ drgn dump_reada.py
re at 0xffff8f3da9d25ad8
logical 38928384
refcnt 1
nzones 1
dev id 0 name b'/dev/sdd'
$So there was one readahead extent with a single zone corresponding to the source device of that last device replace operation logged in dmesg/syslog. Also the ID of that zone's device was 0 which is a special value set in the source device of a device replace operation when the operation finishes (constant BTRFS_DEV_REPLACE_DEVID set at btrfs_dev_replace_finishing()), confirming again that device /dev/sdd was the source of a device replace operation.
Normally there should be as many zones in the readahead extent as there are devices, and I wasn't expecting the extent to be in a block group with a 'single' profile, so I went and confirmed with the following drgn script that there weren't any single profile block groups:
$ cat dump_block_groups.py
import sys
import drgn
from drgn import NULL, Object, cast, container_of, execscript, \
reinterpret, sizeof
from drgn.helpers.linux import * mnt_path = b"/home/fdmanana/btrfs-tests/scratch_1"
mnt = None
for mnt in for_each_mount(prog, dst = mnt_path):
pass
if mnt is None:
sys.stderr.write(f'Error: mount point {mnt_path} not found\n') sys.exit(1)
fs_info = cast('struct btrfs_fs_info *', mnt.mnt.mnt_sb.s_fs_info)
BTRFS_BLOCK_GROUP_DATA = (1 << 0)
BTRFS_BLOCK_GROUP_SYSTEM = (1 << 1)
BTRFS_BLOCK_GROUP_METADATA = (1 << 2)
BTRFS_BLOCK_GROUP_RAID0 = (1 << 3)
BTRFS_BLOCK_GROUP_RAID1 = (1 << 4)
BTRFS_BLOCK_GROUP_DUP = (1 << 5)
BTRFS_BLOCK_GROUP_RAID10 = (1 << 6)
BTRFS_BLOCK_GROUP_RAID5 = (1 << 7)
BTRFS_BLOCK_GROUP_RAID6 = (1 << 8)
BTRFS_BLOCK_GROUP_RAID1C3 = (1 << 9)
BTRFS_BLOCK_GROUP_RAID1C4 = (1 << 10)
def bg_flags_string(bg):
flags = bg.flags.value_()
ret = ''
if flags & BTRFS_BLOCK_GROUP_DATA:
ret = 'data'
if flags & BTRFS_BLOCK_GROUP_METADATA:
if len(ret) > 0:
ret += '|'
ret += 'meta'
if flags & BTRFS_BLOCK_GROUP_SYSTEM:
if len(ret) > 0:
ret += '|'
ret += 'system'
if flags & BTRFS_BLOCK_GROUP_RAID0:
ret += ' raid0'
elif flags & BTRFS_BLOCK_GROUP_RAID1:
ret += ' raid1'
elif flags & BTRFS_BLOCK_GROUP_DUP:
ret += ' dup'
elif flags & BTRFS_BLOCK_GROUP_RAID10:
ret += ' raid10'
elif flags & BTRFS_BLOCK_GROUP_RAID5:
ret += ' raid5'
elif flags & BTRFS_BLOCK_GROUP_RAID6:
ret += ' raid6'
elif flags & BTRFS_BLOCK_GROUP_RAID1C3:
ret += ' raid1c3'
elif flags & BTRFS_BLOCK_GROUP_RAID1C4:
ret += ' raid1c4'
else:
ret += ' single'
return ret def dump_bg(bg):
print()
print(f'block group at {hex(bg.value_())}')
print(f'\t start {bg.start.value_()} length {bg.length.value_()}')
print(f'\t flags {bg.flags.value_()} - {bg_flags_string(bg)}') bg_root = fs_info.block_group_cache_tree.address_of_()
for bg in rbtree_inorder_for_each_entry('struct btrfs_block_group', bg_root, 'cache_node'):
dump_bg(bg)
$ drgn dump_block_groups.py
block group at 0xffff8f3d673b0400
start 22020096 length 16777216
flags 258 - system raid6
block group at 0xffff8f3d53ddb400
start 38797312 length 536870912
flags 260 - meta raid6
block group at 0xffff8f3d5f4d9c00
start 575668224 length 2147483648
flags 257 - data raid6
block group at 0xffff8f3d08189000
start 2723151872 length 67108864
flags 258 - system raid6
block group at 0xffff8f3db70ff000
start 2790260736 length 1073741824
flags 260 - meta raid6
block group at 0xffff8f3d5f4dd800
start 3864002560 length 67108864
flags 258 - system raid6
block group at 0xffff8f3d67037000
start 3931111424 length 2147483648
flags 257 - data raid6
$
So there were only 2 reasons left for having a readahead extent with a single zone: reada_find_zone(), called when creating a readahead extent, returned NULL either because we failed to find the corresponding block group or because a memory allocation failed. With some additional and custom tracing I figured out that on every further ocurrence of the problem the block group had just been deleted when we were looping to create the zones for the readahead extent (at reada_find_extent()), so we ended up with only one zone in the readahead extent, corresponding to a device that ends up getting replaced.
So after figuring that out it became obvious why the hang happens:
1) Task A starts a scrub on any device of the filesystem, except for device /dev/sdd;
2) Task B starts a device replace with /dev/sdd as the source device;
3) Task A calls btrfs_reada_add() from scrub_stripe() and it is currently starting to scrub a stripe from block group X. This call to btrfs_reada_add() is the one for the extent tree. When btrfs_reada_add() calls reada_add_block(), it passes the logical address of the extent tree's root node as its 'logical' argument - a value of 38928384;
4) Task A then enters reada_find_extent(), called from reada_add_block(). It finds there isn't any existing readahead extent for the logical address 38928384, so it proceeds to the path of creating a new one.
It calls btrfs_map_block() to find out which stripes exist for the block group X. On the first iteration of the for loop that iterates over the stripes, it finds the stripe for device /dev/sdd, so it creates one zone for that device and adds it to the readahead extent. Before getting into the second iteration of the loop, the cleanup kthread deletes block group X because it was empty. So in the iterations for the remaining stripes it does not add more zones to the readahead extent, because the calls to reada_find_zone() returned NULL because they couldn't find block group X anymore.
As a result the new readahead extent has a single zone, corresponding to the device /dev/sdd;
4) Before task A returns to btrfs_reada_add() and queues the readahead job for the readahead work queue, task B finishes the device replace and at btrfs_dev_replace_finishing() swaps the device /dev/sdd with the new device /dev/sdg;
5) Task A returns to reada_add_block(), which increments the counter "->elems" of the reada_control structure allocated at btrfs_reada_add().
Then it returns back to btrfs_reada_add() and calls reada_start_machine(). This queues a job in the readahead work queue to run the function reada_start_machine_worker(), which calls __reada_start_machine().
At __reada_start_machine() we take the device list mutex and for each device found in the current device list, we call reada_start_machine_dev() to start the readahead work. However at this point the device /dev/sdd was already freed and is not in the device list anymore.
This means the corresponding readahead for the extent at 38928384 is never started, and therefore the "->elems" counter of the reada_control structure allocated at btrfs_reada_add() never goes down to 0, causing the call to btrfs_reada_wait(), done by the scrub task, to wait forever.
Note that the readahead request can be made either after the device replace started or before it started, however in pratice it is very unlikely that a device replace is able to start after a readahead request is made and is able to complete before the readahead request completes - maybe only on a very small and nearly empty filesystem.
This hang however is not the only problem we can have with readahead and device removals. When the readahead extent has other zones other than the one corresponding to the device that is being removed (either by a device replace or a device remove operation), we risk having a use-after-free on the device when dropping the last reference of the readahead extent.
For example if we create a readahead extent with two zones, one for the device /dev/sdd and one for the device /dev/sde:
1) Before the readahead worker starts, the device /dev/sdd is removed, and the corresponding btrfs_device structure is freed. However the readahead extent still has the zone pointing to the device structure;
2) When the readahead worker starts, it only finds device /dev/sde in the current device list of the filesystem;
3) It starts the readahead work, at reada_start_machine_dev(), using the device /dev/sde;
4) Then when it finishes reading the extent from device /dev/sde, it calls __readahead_hook() which ends up dropping the last reference on the readahead extent through the last call to reada_extent_put();
5) At reada_extent_put() it iterates over each zone of the readahead extent and attempts to delete an element from the device's 'reada_extents' radix tree, resulting in a use-after-free, as the device pointer of the zone for /dev/sdd is now stale. We can also access the device after dropping the last reference of a zone, through reada_zone_release(), also called by reada_extent_put().
And a device remove suffers the same problem, however since it shrinks the device size down to zero before removing the device, it is very unlikely to still have readahead requests not completed by the time we free the device, the only possibility is if the device has a very little space allocated.
While the hang problem is exclusive to scrub, since it is currently the only user of btrfs_reada_add() and btrfs_reada_wait(), the use-after-free problem affects any path that triggers readhead, which includes btree_readahead_hook() and __readahead_hook() (a readahead worker can trigger readahed for the children of a node) for example - any path that ends up calling reada_add_block() can trigger the use-after-free after a device is removed.
So fix this by waiting for any readahead requests for a device to complete before removing a device, ensuring that while waiting for existing ones no new ones can be made.
This problem has been around for a very long time - the readahead code was added in 2011, device remove exists since 2008 and device replace was introduced in 2013, hard to pick a specific commit for a git Fixes tag.
--- fs/btrfs/ctree.h | 2 ++ fs/btrfs/dev-replace.c | 5 +++++ fs/btrfs/reada.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ fs/btrfs/volumes.c | 3 +++ fs/btrfs/volumes.h | 1 + 5 files changed, 56 insertions(+)
fs/btrfs/ctree.h +2 -0
@@ -3517,6 +3517,8 @@ struct reada_control *btrfs_reada_add(stint btrfs_reada_wait (void *handle);void btrfs_reada_detach (void *handle);int btree_readahead_hook (struct extent_buffer *eb,int err); +void btrfs_reada_remove_dev (struct btrfs_device *dev); +void btrfs_reada_undo_remove_dev (struct btrfs_device *dev);static inline int is_fstree (u64 rootid) {
fs/btrfs/dev-replace.c +5 -0
@@ -668,6 +668,9 @@ static int btrfs_dev_replace_finishing(s }btrfs_wait_ordered_roots (fs_info,U64_MAX ,0 , (u64)-1 ); +if (!scrub_ret) +btrfs_reada_remove_dev (src_device); +/* * We have to use this loop approach because at this point src_device * has to be available for transaction commit to complete, yet new
@@ -676,6 +679,7 @@ static int btrfs_dev_replace_finishing(swhile (1 ) { trans =btrfs_start_transaction (root,0 );if (IS_ERR (trans)) { +btrfs_reada_undo_remove_dev (src_device);mutex_unlock (&dev_replace->lock_finishing_cancel_unmount);return PTR_ERR (trans); }
@@ -726,6 +730,7 @@ error:up_write (&dev_replace->rwsem);mutex_unlock (&fs_info->chunk_mutex);mutex_unlock (&fs_info->fs_devices->device_list_mutex); +btrfs_reada_undo_remove_dev (src_device);btrfs_rm_dev_replace_blocked (fs_info);if (tgt_device)btrfs_destroy_dev_replace_tgtdev (tgt_device);
fs/btrfs/reada.c +45 -0
54 lines not on this page · raw message
fs/btrfs/volumes.c +3 -0
@@ -2104,6 +2104,8 @@ int btrfs_rm_device(struct btrfs_fs_infomutex_unlock (&uuid_mutex); ret =btrfs_shrink_device (device,0 ); +if (!ret) +btrfs_reada_remove_dev (device);mutex_lock (&uuid_mutex);if (ret) goto error_undo;
@@ -2191,6 +2193,7 @@ out:return ret; error_undo: +btrfs_reada_undo_remove_dev (device);if (test_bit (BTRFS_DEV_STATE_WRITEABLE , &device->dev_state)) {mutex_lock (&fs_info->chunk_mutex); list_add(&device->dev_alloc_list,
fs/btrfs/volumes.h +1 -0
@@ -50,6 +50,7 @@ struct btrfs_io_geometry {#define BTRFS_DEV_STATE_MISSING (2)#define BTRFS_DEV_STATE_REPLACE_TGT (3)#define BTRFS_DEV_STATE_FLUSH_SENT (4) +#define BTRFS_DEV_STATE_NO_READA (5)struct btrfs_device {struct list_head dev_list;/* device_list_mutex */
Greg Kroah-Hartman
maintainerPATCH 237/391 btrfs: drop the path before adding block group sysfs files
In reply to Greg Kroah-HartmanFrom: Josef Bacik <[email protected]>
commit 7837fa88704a66257404bb14144c9e4ab631a28a upstream.
Dave reported a problem with my rwsem conversion patch where we got the following lockdep splat:
======================================================
WARNING: possible circular locking dependency detected
5.9.0-default+ #1297 Not tainted
------------------------------------------------------
kswapd0/76 is trying to acquire lock:
ffff9d5d25df2530 (&delayed_node->mutex){+.+.}-{3:3}, at: __btrfs_release_delayed_node.part.0+0x3f/0x320 [btrfs]
but task is already holding lock:
ffffffffa40cbba0 (fs_reclaim){+.+.}-{0:0}, at: __fs_reclaim_acquire+0x5/0x30
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #4 (fs_reclaim){+.+.}-{0:0}:
__lock_acquire+0x582/0xac0 lock_acquire+0xca/0x430 fs_reclaim_acquire.part.0+0x25/0x30 kmem_cache_alloc+0x30/0x9c0 alloc_inode+0x81/0x90 iget_locked+0xcd/0x1a0 kernfs_get_inode+0x1b/0x130 kernfs_get_tree+0x136/0x210 sysfs_get_tree+0x1a/0x50 vfs_get_tree+0x1d/0xb0 path_mount+0x70f/0xa80 do_mount+0x75/0x90 __x64_sys_mount+0x8e/0xd0 do_syscall_64+0x2d/0x70 entry_SYSCALL_64_after_hwframe+0x44/0xa9
-> #3 (kernfs_mutex){+.+.}-{3:3}:
__lock_acquire+0x582/0xac0 lock_acquire+0xca/0x430 __mutex_lock+0xa0/0xaf0 kernfs_add_one+0x23/0x150 kernfs_create_dir_ns+0x58/0x80 sysfs_create_dir_ns+0x70/0xd0 kobject_add_internal+0xbb/0x2d0 kobject_add+0x7a/0xd0 btrfs_sysfs_add_block_group_type+0x141/0x1d0 [btrfs] btrfs_read_block_groups+0x1f1/0x8c0 [btrfs] open_ctree+0x981/0x1108 [btrfs] btrfs_mount_root.cold+0xe/0xb0 [btrfs] legacy_get_tree+0x2d/0x60 vfs_get_tree+0x1d/0xb0 fc_mount+0xe/0x40 vfs_kern_mount.part.0+0x71/0x90 btrfs_mount+0x13b/0x3e0 [btrfs] legacy_get_tree+0x2d/0x60 vfs_get_tree+0x1d/0xb0 path_mount+0x70f/0xa80 do_mount+0x75/0x90 __x64_sys_mount+0x8e/0xd0 do_syscall_64+0x2d/0x70 entry_SYSCALL_64_after_hwframe+0x44/0xa9
-> #2 (btrfs-extent-00){++++}-{3:3}:
__lock_acquire+0x582/0xac0 lock_acquire+0xca/0x430 down_read_nested+0x45/0x220 __btrfs_tree_read_lock+0x35/0x1c0 [btrfs] __btrfs_read_lock_root_node+0x3a/0x50 [btrfs] btrfs_search_slot+0x6d4/0xfd0 [btrfs] check_committed_ref+0x69/0x200 [btrfs] btrfs_cross_ref_exist+0x65/0xb0 [btrfs] run_delalloc_nocow+0x446/0x9b0 [btrfs] btrfs_run_delalloc_range+0x61/0x6a0 [btrfs] writepage_delalloc+0xae/0x160 [btrfs] __extent_writepage+0x262/0x420 [btrfs] extent_write_cache_pages+0x2b6/0x510 [btrfs] extent_writepages+0x43/0x90 [btrfs] do_writepages+0x40/0xe0 __writeback_single_inode+0x62/0x610 writeback_sb_inodes+0x20f/0x500 wb_writeback+0xef/0x4a0 wb_do_writeback+0x49/0x2e0 wb_workfn+0x81/0x340 process_one_work+0x233/0x5d0 worker_thread+0x50/0x3b0 kthread+0x137/0x150 ret_from_fork+0x1f/0x30
-> #1 (btrfs-fs-00){++++}-{3:3}:
__lock_acquire+0x582/0xac0 lock_acquire+0xca/0x430 down_read_nested+0x45/0x220 __btrfs_tree_read_lock+0x35/0x1c0 [btrfs] __btrfs_read_lock_root_node+0x3a/0x50 [btrfs] btrfs_search_slot+0x6d4/0xfd0 [btrfs] btrfs_lookup_inode+0x3a/0xc0 [btrfs] __btrfs_update_delayed_inode+0x93/0x2c0 [btrfs] __btrfs_commit_inode_delayed_items+0x7de/0x850 [btrfs] __btrfs_run_delayed_items+0x8e/0x140 [btrfs] btrfs_commit_transaction+0x367/0xbc0 [btrfs] btrfs_mksubvol+0x2db/0x470 [btrfs] btrfs_mksnapshot+0x7b/0xb0 [btrfs] __btrfs_ioctl_snap_create+0x16f/0x1a0 [btrfs] btrfs_ioctl_snap_create_v2+0xb0/0xf0 [btrfs] btrfs_ioctl+0xd0b/0x2690 [btrfs] __x64_sys_ioctl+0x6f/0xa0 do_syscall_64+0x2d/0x70 entry_SYSCALL_64_after_hwframe+0x44/0xa9
-> #0 (&delayed_node->mutex){+.+.}-{3:3}:
check_prev_add+0x91/0xc60 validate_chain+0xa6e/0x2a20 __lock_acquire+0x582/0xac0 lock_acquire+0xca/0x430 __mutex_lock+0xa0/0xaf0 __btrfs_release_delayed_node.part.0+0x3f/0x320 [btrfs] btrfs_evict_inode+0x3cc/0x560 [btrfs] evict+0xd6/0x1c0 dispose_list+0x48/0x70 prune_icache_sb+0x54/0x80 super_cache_scan+0x121/0x1a0 do_shrink_slab+0x16d/0x3b0 shrink_slab+0xb1/0x2e0 shrink_node+0x230/0x6a0 balance_pgdat+0x325/0x750 kswapd+0x206/0x4d0 kthread+0x137/0x150 ret_from_fork+0x1f/0x30
other info that might help us debug this:
Chain exists of:
&delayed_node->mutex --> kernfs_mutex --> fs_reclaim
Possible unsafe locking scenario: CPU0 CPU1
---- ----
lock(fs_reclaim);
lock(kernfs_mutex);
lock(fs_reclaim);
lock(&delayed_node->mutex);*** DEADLOCK ***
3 locks held by kswapd0/76:
#0: ffffffffa40cbba0 (fs_reclaim){+.+.}-{0:0}, at: __fs_reclaim_acquire+0x5/0x30 #1: ffffffffa40b8b58 (shrinker_rwsem){++++}-{3:3}, at: shrink_slab+0x54/0x2e0 #2: ffff9d5d322390e8 (&type->s_umount_key#26){++++}-{3:3}, at: trylock_super+0x16/0x50
stack backtrace: CPU: 2 PID: 76 Comm: kswapd0 Not tainted 5.9.0-default+ #1297 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-59-gc9ba527-rebuilt.opensuse.org 04/01/2014 Call Trace: dump_stack+0x77/0x97 check_noncircular+0xff/0x110 ? save_trace+0x50/0x470 check_prev_add+0x91/0xc60 validate_chain+0xa6e/0x2a20 ? save_trace+0x50/0x470 __lock_acquire+0x582/0xac0 lock_acquire+0xca/0x430 ? __btrfs_release_delayed_node.part.0+0x3f/0x320 [btrfs] __mutex_lock+0xa0/0xaf0 ? __btrfs_release_delayed_node.part.0+0x3f/0x320 [btrfs] ? __lock_acquire+0x582/0xac0 ? __btrfs_release_delayed_node.part.0+0x3f/0x320 [btrfs] ? btrfs_evict_inode+0x30b/0x560 [btrfs] ? __btrfs_release_delayed_node.part.0+0x3f/0x320 [btrfs] __btrfs_release_delayed_node.part.0+0x3f/0x320 [btrfs] btrfs_evict_inode+0x3cc/0x560 [btrfs] evict+0xd6/0x1c0 dispose_list+0x48/0x70 prune_icache_sb+0x54/0x80 super_cache_scan+0x121/0x1a0 do_shrink_slab+0x16d/0x3b0 shrink_slab+0xb1/0x2e0 shrink_node+0x230/0x6a0 balance_pgdat+0x325/0x750 kswapd+0x206/0x4d0 ? finish_wait+0x90/0x90 ? balance_pgdat+0x750/0x750 kthread+0x137/0x150 ? kthread_mod_delayed_work+0xc0/0xc0 ret_from_fork+0x1f/0x30
This happens because we are still holding the path open when we start adding the sysfs files for the block groups, which creates a dependency on fs_reclaim via the tree lock. Fix this by dropping the path before we start doing anything with sysfs.
--- fs/btrfs/block-group.c | 1 + 1 file changed, 1 insertion(+)
fs/btrfs/block-group.c +1 -0
@@ -2034,6 +2034,7 @@ int btrfs_read_block_groups(struct btrfs key.offset =0 ;btrfs_release_path (path); } +btrfs_release_path (path);rcu_read_lock ();list_for_each_entry_rcu (space_info, &info->space_info, list) {
Greg Kroah-Hartman
maintainerPATCH 238/391 usb: xhci: Workaround for S3 issue on AMD SNPS 3.0 xHC
In reply to Greg Kroah-HartmanFrom: Sandeep Singh <[email protected]>
commit 2a632815683d2d34df52b701a36fe5ac6654e719 upstream.
On some platform of AMD, S3 fails with HCE and SRE errors. To fix this, need to disable a bit which is enable in sparse controller.
--- drivers/usb/host/xhci-pci.c | 17 +++++++++++++++++ drivers/usb/host/xhci.h | 1 + 2 files changed, 18 insertions(+)
drivers/usb/host/xhci-pci.c +17 -0
@@ -22,6 +22,8 @@#define SSIC_PORT_CFG2_OFFSET 0x30#define PROG_DONE (1 << 30)#define SSIC_PORT_UNUSED (1 << 31) +#define SPARSE_DISABLE_BIT 17 +#define SPARSE_CNTL_ENABLE 0xC12C/* Device for a quirk */ #define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
@@ -160,6 +162,9 @@ static void xhci_pci_quirks(struct devic (pdev->device == 0x15e0 || pdev->device == 0x15e1)) xhci->quirks |= XHCI_SNPS_BROKEN_SUSPEND; +if (pdev->vendor ==PCI_VENDOR_ID_AMD && pdev->device ==0x15e5 ) + xhci->quirks |=XHCI_DISABLE_SPARSE ; +if (pdev->vendor ==PCI_VENDOR_ID_AMD ) xhci->quirks |=XHCI_TRUST_TX_LENGTH ;
@@ -490,6 +495,15 @@ static void xhci_pme_quirk(struct usb_hcreadl (reg); } +static void xhci_sparse_control_quirk (struct usb_hcd *hcd) +{ +u32 reg; + + reg =readl (hcd->regs +SPARSE_CNTL_ENABLE ); + reg &= ~BIT (SPARSE_DISABLE_BIT ); +writel (reg, hcd->regs +SPARSE_CNTL_ENABLE ); +} +static int xhci_pci_suspend (struct usb_hcd *hcd,bool do_wakeup) {struct xhci_hcd *xhci =hcd_to_xhci (hcd);
@@ -509,6 +523,9 @@ static int xhci_pci_suspend(struct usb_hif (xhci->quirks &XHCI_SSIC_PORT_UNUSED )xhci_ssic_port_unused_quirk (hcd, true); +if (xhci->quirks &XHCI_DISABLE_SPARSE ) +xhci_sparse_control_quirk (hcd); + ret =xhci_suspend (xhci, do_wakeup);if (ret && (xhci->quirks &XHCI_SSIC_PORT_UNUSED ))xhci_ssic_port_unused_quirk (hcd, false);
drivers/usb/host/xhci.h +1 -0
@@ -1874,6 +1874,7 @@ struct xhci_hcd {#define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34)#define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35)#define XHCI_RENESAS_FW_QUIRK BIT_ULL(36) +#define XHCI_DISABLE_SPARSE BIT_ULL(38)unsigned int num_active_eps;unsigned int limit_active_eps;
Greg Kroah-Hartman
maintainerPATCH 239/391 usb: dwc3: pci: Allow Elkhart Lake to utilize DSM method for PM functionality
In reply to Greg Kroah-HartmanFrom: Raymond Tan <[email protected]>
commit a609ce2a13360d639b384b6ca783b38c1247f2db upstream.
Similar to some other IA platforms, Elkhart Lake too depends on the PMU register write to request transition of Dx power state.
Thus, we add the PCI_DEVICE_ID_INTEL_EHLLP to the list of devices that shall execute the ACPI _DSM method during D0/D3 sequence.
[[email protected]: included Fixes tag]
--- drivers/usb/dwc3/dwc3-pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/usb/dwc3/dwc3-pci.c +2 -1
@@ -147,7 +147,8 @@ static int dwc3_pci_quirks(struct dwc3_pif (pdev->vendor ==PCI_VENDOR_ID_INTEL ) {if (pdev->device ==PCI_DEVICE_ID_INTEL_BXT || - pdev->device ==PCI_DEVICE_ID_INTEL_BXT_M ) { + pdev->device ==PCI_DEVICE_ID_INTEL_BXT_M || + pdev->device ==PCI_DEVICE_ID_INTEL_EHLLP ) {guid_parse (PCI_INTEL_BXT_DSM_GUID , &dwc->guid); dwc->has_dsm_for_pm = true; }
Greg Kroah-Hartman
maintainerPATCH 240/391 usb: dwc3: ep0: Fix ZLP for OUT ep0 requests
In reply to Greg Kroah-HartmanFrom: Thinh Nguyen <[email protected]>
commit 66706077dc89c66a4777a4c6298273816afb848c upstream.
The current ZLP handling for ep0 requests is only for control IN requests. For OUT direction, DWC3 needs to check and setup for MPS alignment.
Usually, control OUT requests can indicate its transfer size via the wLength field of the control message. So usb_request->zero is usually not needed for OUT direction. To handle ZLP OUT for control endpoint, make sure the TRB is MPS size.
--- drivers/usb/dwc3/ep0.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
drivers/usb/dwc3/ep0.c +9 -2
@@ -942,12 +942,16 @@ static void dwc3_ep0_xfer_complete(strucstatic void __dwc3_ep0_do_control_data (struct dwc3 *dwc,struct dwc3_ep *dep,struct dwc3_request *req) { +unsigned int trb_length =0 ;int ret; req->direction = !!dep->number;if (req->request.length ==0 ) { -dwc3_ep0_prepare_one_trb (dep, dwc->ep0_trb_addr,0 , +if (!req->direction) + trb_length = dep->endpoint.maxpacket; + +dwc3_ep0_prepare_one_trb (dep, dwc->bounce_addr, trb_length,DWC3_TRBCTL_CONTROL_DATA , false); ret =dwc3_ep0_start_trans (dep); } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket)
@@ -994,9 +998,12 @@ static void __dwc3_ep0_do_control_data(s req->trb = &dwc->ep0_trb[dep->trb_enqueue -1 ]; +if (!req->direction) + trb_length = dep->endpoint.maxpacket; +/* Now prepare one extra TRB to align transfer size */ dwc3_ep0_prepare_one_trb (dep, dwc->bounce_addr, -0 ,DWC3_TRBCTL_CONTROL_DATA , + trb_length,DWC3_TRBCTL_CONTROL_DATA , false); ret =dwc3_ep0_start_trans (dep); }else {
Greg Kroah-Hartman
maintainerPATCH 241/391 usb: dwc3: gadget: Check MPS of the request length
In reply to Greg Kroah-HartmanFrom: Thinh Nguyen <[email protected]>
commit ca3df3468eec87f6374662f7de425bc44c3810c1 upstream.
When preparing for SG, not all the entries are prepared at once. When resume, don't use the remaining request length to calculate for MPS alignment. Use the entire request->length to do that.
--- drivers/usb/dwc3/gadget.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/usb/dwc3/gadget.c +2 -2
@@ -1095,6 +1095,8 @@ static void dwc3_prepare_one_trb_sg(strustruct scatterlist *s;int i;unsigned int length = req->request.length; +unsigned int maxp =usb_endpoint_maxp (dep->endpoint.desc); +unsigned int rem = length % maxp;unsigned int remaining = req->request.num_mapped_sgs - req->num_queued_sgs;
@@ -1106,8 +1108,6 @@ static void dwc3_prepare_one_trb_sg(stru length -=sg_dma_len (s);for_each_sg (sg, s, remaining, i) { -unsigned int maxp =usb_endpoint_maxp (dep->endpoint.desc); -unsigned int rem = length % maxp;unsigned int trb_length;unsigned chain = true;
Greg Kroah-Hartman
maintainerPATCH 242/391 usb: dwc3: gadget: Reclaim extra TRBs after request completion
In reply to Greg Kroah-HartmanFrom: Thinh Nguyen <[email protected]>
commit 690e5c2dc29f8891fcfd30da67e0d5837c2c9df5 upstream.
An SG request may be partially completed (due to no available TRBs). Don't reclaim extra TRBs and clear the needs_extra_trb flag until the request is fully completed. Otherwise, the driver will reclaim the wrong TRB.
--- drivers/usb/dwc3/gadget.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/usb/dwc3/gadget.c +5 -5
@@ -2732,6 +2732,11 @@ static int dwc3_gadget_ep_cleanup_comple ret =dwc3_gadget_ep_reclaim_trb_linear (dep, req, event, status); + req->request.actual = req->request.length - req->remaining; + +if (!dwc3_gadget_ep_request_completed (req)) + goto out; +if (req->needs_extra_trb) {unsigned int maxp =usb_endpoint_maxp (dep->endpoint.desc);
@@ -2747,11 +2752,6 @@ static int dwc3_gadget_ep_cleanup_comple req->needs_extra_trb = false; } - req->request.actual = req->request.length - req->remaining; - -if (!dwc3_gadget_ep_request_completed (req)) - goto out; -dwc3_gadget_giveback (dep, req, status); out:
Greg Kroah-Hartman
maintainerPATCH 243/391 usb: dwc3: core: add phy cleanup for probe error handling
In reply to Greg Kroah-HartmanFrom: Li Jun <[email protected]>
commit 03c1fd622f72c7624c81b64fdba4a567ae5ee9cb upstream.
Add the phy cleanup if dwc3 mode init fail, which is the missing part of de-init for dwc3 core init.
--- drivers/usb/dwc3/core.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
drivers/usb/dwc3/core.c +11 -0
@@ -1564,6 +1564,17 @@ static int dwc3_probe(struct platform_de err5:dwc3_event_buffers_cleanup (dwc); + +usb_phy_shutdown (dwc->usb2_phy); +usb_phy_shutdown (dwc->usb3_phy); +phy_exit (dwc->usb2_generic_phy); +phy_exit (dwc->usb3_generic_phy); + +usb_phy_set_suspend (dwc->usb2_phy,1 ); +usb_phy_set_suspend (dwc->usb3_phy,1 ); +phy_power_off (dwc->usb2_generic_phy); +phy_power_off (dwc->usb3_generic_phy); +dwc3_ulpi_exit (dwc); err4:
Greg Kroah-Hartman
maintainerPATCH 244/391 usb: dwc3: core: dont trigger runtime pm when remove driver
In reply to Greg Kroah-HartmanFrom: Li Jun <[email protected]>
commit 266d0493900ac5d6a21cdbe6b1624ed2da94d47a upstream.
No need to trigger runtime pm in driver removal, otherwise if user disable auto suspend via sys file, runtime suspend may be entered, which will call dwc3_core_exit() again and there will be clock disable not balance warning:
[ 2026.820154] xhci-hcd xhci-hcd.0.auto: remove, state 4 [ 2026.825268] usb usb2: USB disconnect, device number 1 [ 2026.831017] xhci-hcd xhci-hcd.0.auto: USB bus 2 deregistered [ 2026.836806] xhci-hcd xhci-hcd.0.auto: remove, state 4 [ 2026.842029] usb usb1: USB disconnect, device number 1 [ 2026.848029] xhci-hcd xhci-hcd.0.auto: USB bus 1 deregistered [ 2026.865889] ------------[ cut here ]------------ [ 2026.870506] usb2_ctrl_root_clk already disabled [ 2026.875082] WARNING: CPU: 0 PID: 731 at drivers/clk/clk.c:958 clk_core_disable+0xa0/0xa8 [ 2026.883170] Modules linked in: dwc3(-) phy_fsl_imx8mq_usb [last unloaded: dwc3] [ 2026.890488] CPU: 0 PID: 731 Comm: rmmod Not tainted 5.8.0-rc7-00280-g9d08cca-dirty #245 [ 2026.898489] Hardware name: NXP i.MX8MQ EVK (DT) [ 2026.903020] pstate: 20000085 (nzCv daIf -PAN -UAO BTYPE=--) [ 2026.908594] pc : clk_core_disable+0xa0/0xa8 [ 2026.912777] lr : clk_core_disable+0xa0/0xa8 [ 2026.916958] sp : ffff8000121b39a0 [ 2026.920271] x29: ffff8000121b39a0 x28: ffff0000b11f3700 [ 2026.925583] x27: 0000000000000000 x26: ffff0000b539c700 [ 2026.930895] x25: 000001d7e44e1232 x24: ffff0000b76fa800 [ 2026.936208] x23: ffff0000b76fa6f8 x22: ffff800008d01040 [ 2026.941520] x21: ffff0000b539ce00 x20: ffff0000b7105000 [ 2026.946832] x19: ffff0000b7105000 x18: 0000000000000010 [ 2026.952144] x17: 0000000000000001 x16: 0000000000000000 [ 2026.957456] x15: ffff0000b11f3b70 x14: ffffffffffffffff [ 2026.962768] x13: ffff8000921b36f7 x12: ffff8000121b36ff [ 2026.968080] x11: ffff8000119e1000 x10: ffff800011bf26d0 [ 2026.973392] x9 : 0000000000000000 x8 : ffff800011bf3000 [ 2026.978704] x7 : ffff800010695d68 x6 : 0000000000000252 [ 2026.984016] x5 : ffff0000bb9881f0 x4 : 0000000000000000 [ 2026.989327] x3 : 0000000000000027 x2 : 0000000000000023 [ 2026.994639] x1 : ac2fa471aa7cab00 x0 : 0000000000000000 [ 2026.999951] Call trace: [ 2027.002401] clk_core_disable+0xa0/0xa8 [ 2027.006238] clk_core_disable_lock+0x20/0x38 [ 2027.010508] clk_disable+0x1c/0x28 [ 2027.013911] clk_bulk_disable+0x34/0x50 [ 2027.017758] dwc3_core_exit+0xec/0x110 [dwc3] [ 2027.022122] dwc3_suspend_common+0x84/0x188 [dwc3] [ 2027.026919] dwc3_runtime_suspend+0x74/0x9c [dwc3] [ 2027.031712] pm_generic_runtime_suspend+0x28/0x40 [ 2027.036419] genpd_runtime_suspend+0xa0/0x258 [ 2027.040777] __rpm_callback+0x88/0x140 [ 2027.044526] rpm_callback+0x20/0x80 [ 2027.048015] rpm_suspend+0xd0/0x418 [ 2027.051503] __pm_runtime_suspend+0x58/0xa0 [ 2027.055693] dwc3_runtime_idle+0x7c/0x90 [dwc3] [ 2027.060224] __rpm_callback+0x88/0x140 [ 2027.063973] rpm_idle+0x78/0x150 [ 2027.067201] __pm_runtime_idle+0x58/0xa0 [ 2027.071130] dwc3_remove+0x64/0xc0 [dwc3] [ 2027.075140] platform_drv_remove+0x28/0x48 [ 2027.079239] device_release_driver_internal+0xf4/0x1c0 [ 2027.084377] driver_detach+0x4c/0xd8 [ 2027.087954] bus_remove_driver+0x54/0xa8 [ 2027.091877] driver_unregister+0x2c/0x58 [ 2027.095799] platform_driver_unregister+0x10/0x18 [ 2027.100509] dwc3_driver_exit+0x14/0x1408 [dwc3] [ 2027.105129] __arm64_sys_delete_module+0x178/0x218 [ 2027.109922] el0_svc_common.constprop.0+0x68/0x160 [ 2027.114714] do_el0_svc+0x20/0x80 [ 2027.118031] el0_sync_handler+0x88/0x190 [ 2027.121953] el0_sync+0x140/0x180 [ 2027.125267] ---[ end trace 027f4f8189958f1f ]--- [ 2027.129976] ------------[ cut here ]------------
--- drivers/usb/dwc3/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/usb/dwc3/core.c +2 -2
@@ -1610,9 +1610,9 @@ static int dwc3_remove(struct platform_ddwc3_core_exit (dwc);dwc3_ulpi_exit (dwc); -pm_runtime_put_sync (&pdev->dev); -pm_runtime_allow (&pdev->dev);pm_runtime_disable (&pdev->dev); +pm_runtime_put_noidle (&pdev->dev); +pm_runtime_set_suspended (&pdev->dev);dwc3_free_event_buffers (dwc);dwc3_free_scratch_buffers (dwc);
Greg Kroah-Hartman
maintainerPATCH 245/391 usb: dwc3: gadget: Resume pending requests after CLEAR_STALL
In reply to Greg Kroah-HartmanFrom: Thinh Nguyen <[email protected]>
commit c503672abe1348f10f5a54a662336358c6e1a297 upstream.
The function driver may queue new requests right after halting the endpoint (i.e. queue new requests while the endpoint is stalled). There's no restriction preventing it from doing so. However, dwc3 currently drops those requests after CLEAR_STALL. The driver should only drop started requests. Keep the pending requests in the pending list to resume and process them after the host issues ClearFeature(Halt) to the endpoint.
--- drivers/usb/dwc3/gadget.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-)
drivers/usb/dwc3/gadget.c +14 -8
@@ -1628,8 +1628,13 @@ static int __dwc3_gadget_ep_queue(structif (dep->flags &DWC3_EP_WAIT_TRANSFER_COMPLETE )return 0 ; -/* Start the transfer only after the END_TRANSFER is completed */ -if (dep->flags &DWC3_EP_END_TRANSFER_PENDING ) { +/* +* Start the transfer only after the END_TRANSFER is completed +* and endpoint STALL is cleared. +*/ +if ((dep->flags &DWC3_EP_END_TRANSFER_PENDING ) || + (dep->flags &DWC3_EP_WEDGE ) || + (dep->flags &DWC3_EP_STALL )) { dep->flags |=DWC3_EP_DELAY_START ;return 0 ; }
@@ -1836,13 +1841,14 @@ int __dwc3_gadget_ep_set_halt(struct dwclist_for_each_entry_safe (req, tmp, &dep->started_list, list)dwc3_gadget_move_cancelled_request (req); -list_for_each_entry_safe (req, tmp, &dep->pending_list, list) -dwc3_gadget_move_cancelled_request (req); - -if (!(dep->flags &DWC3_EP_END_TRANSFER_PENDING )) { - dep->flags &= ~DWC3_EP_DELAY_START ; +if (!(dep->flags &DWC3_EP_END_TRANSFER_PENDING ))dwc3_gadget_ep_cleanup_cancelled_requests (dep); - } + +if ((dep->flags &DWC3_EP_DELAY_START ) && + !usb_endpoint_xfer_isoc (dep->endpoint.desc)) +__dwc3_gadget_kick_transfer (dep); + + dep->flags &= ~DWC3_EP_DELAY_START ; }return ret;
Greg Kroah-Hartman
maintainerPATCH 246/391 usb: dwc3: gadget: END_TRANSFER before CLEAR_STALL command
In reply to Greg Kroah-HartmanFrom: Thinh Nguyen <[email protected]>
commit d97c78a1908e59a1fdbcbece87cd0440b5d7a1f2 upstream.
According the programming guide (for all DWC3 IPs), when the driver handles ClearFeature(halt) request, it should issue CLEAR_STALL command _after_ the END_TRANSFER command completes. The END_TRANSFER command may take some time to complete. So, delay the ClearFeature(halt) request control status stage and wait for END_TRANSFER command completion interrupt. Only after END_TRANSFER command completes that the driver may issue CLEAR_STALL command.
--- drivers/usb/dwc3/core.h | 1 + drivers/usb/dwc3/ep0.c | 16 ++++++++++++++++ drivers/usb/dwc3/gadget.c | 40 ++++++++++++++++++++++++++++++++-------- drivers/usb/dwc3/gadget.h | 1 + 4 files changed, 50 insertions(+), 8 deletions(-)
drivers/usb/dwc3/core.h +1 -0
@@ -710,6 +710,7 @@ struct dwc3_ep {#define DWC3_EP_IGNORE_NEXT_NOSTREAM BIT(8)#define DWC3_EP_FORCE_RESTART_STREAM BIT(9)#define DWC3_EP_FIRST_STREAM_PRIMED BIT(10) +#define DWC3_EP_PENDING_CLEAR_STALL BIT(11)/* This last one is specific to EP0 */ #define DWC3_EP0_DIR_IN BIT(31)
drivers/usb/dwc3/ep0.c +16 -0
@@ -524,6 +524,11 @@ static int dwc3_ep0_handle_endpoint(stru ret =__dwc3_gadget_ep_set_halt (dep, set, true);if (ret)return -EINVAL ; + +/* ClearFeature(Halt) may need delayed status */ +if (!set && (dep->flags &DWC3_EP_END_TRANSFER_PENDING )) +return USB_GADGET_DELAYED_STATUS ; +break ;default :return -EINVAL ;
@@ -1049,6 +1054,17 @@ static void dwc3_ep0_do_control_status(s__dwc3_ep0_do_control_status (dwc, dep); } +void dwc3_ep0_send_delayed_status (struct dwc3 *dwc) +{ +unsigned int direction = !dwc->ep0_expect_in; + +if (dwc->ep0state !=EP0_STATUS_PHASE ) +return ; + + dwc->delayed_status = false; +__dwc3_ep0_do_control_status (dwc, dwc->eps[direction]); +} +static void dwc3_ep0_end_control_data (struct dwc3 *dwc,struct dwc3_ep *dep) {struct dwc3_gadget_ep_cmd_params params;
drivers/usb/dwc3/gadget.c +32 -8
@@ -1827,6 +1827,18 @@ int __dwc3_gadget_ep_set_halt(struct dwcreturn 0 ; } +dwc3_stop_active_transfer (dep, true, true); + +list_for_each_entry_safe (req, tmp, &dep->started_list, list) +dwc3_gadget_move_cancelled_request (req); + +if (dep->flags &DWC3_EP_END_TRANSFER_PENDING ) { + dep->flags |=DWC3_EP_PENDING_CLEAR_STALL ; +return 0 ; + } + +dwc3_gadget_ep_cleanup_cancelled_requests (dep); + ret =dwc3_send_clear_stall_ep_cmd (dep);if (ret) { dev_err(dwc->dev, "failed to clear STALL on %s\n",
@@ -1836,14 +1848,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc dep->flags &= ~(DWC3_EP_STALL |DWC3_EP_WEDGE ); -dwc3_stop_active_transfer (dep, true, true); - -list_for_each_entry_safe (req, tmp, &dep->started_list, list) -dwc3_gadget_move_cancelled_request (req); - -if (!(dep->flags &DWC3_EP_END_TRANSFER_PENDING )) -dwc3_gadget_ep_cleanup_cancelled_requests (dep); -if ((dep->flags &DWC3_EP_DELAY_START ) && !usb_endpoint_xfer_isoc (dep->endpoint.desc))__dwc3_gadget_kick_transfer (dep);
@@ -3003,6 +3007,26 @@ static void dwc3_endpoint_interrupt(stru dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING ; dep->flags &= ~DWC3_EP_TRANSFER_STARTED ;dwc3_gadget_ep_cleanup_cancelled_requests (dep); + +if (dep->flags &DWC3_EP_PENDING_CLEAR_STALL ) { +struct dwc3 *dwc = dep->dwc; + + dep->flags &= ~DWC3_EP_PENDING_CLEAR_STALL ; +if (dwc3_send_clear_stall_ep_cmd (dep)) { +struct usb_ep *ep0 = &dwc->eps[0 ]->endpoint; + +dev_err (dwc->dev,"failed to clear STALL on %s\n" , + dep->name); +if (dwc->delayed_status) +__dwc3_gadget_ep0_set_halt (ep0,1 ); +return ; + } + + dep->flags &= ~(DWC3_EP_STALL |DWC3_EP_WEDGE ); +if (dwc->delayed_status) +dwc3_ep0_send_delayed_status (dwc); + } +if ((dep->flags &DWC3_EP_DELAY_START ) && !usb_endpoint_xfer_isoc (dep->endpoint.desc))__dwc3_gadget_kick_transfer (dep);
drivers/usb/dwc3/gadget.h +1 -0
@@ -113,6 +113,7 @@ int dwc3_gadget_ep0_set_halt(struct usb_int dwc3_gadget_ep0_queue (struct usb_ep *ep,struct usb_request *request,gfp_t gfp_flags);int __dwc3_gadget_ep_set_halt (struct dwc3_ep *dep,int value,int protocol); +void dwc3_ep0_send_delayed_status (struct dwc3 *dwc);/** * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW
Greg Kroah-Hartman
maintainerPATCH 247/391 usb: cdns3: Fix on-chip memory overflow issue
In reply to Greg Kroah-HartmanFrom: Pawel Laszczak <[email protected]>
commit 52d3967704aea6cb316d419a33a5e1d56d33a3c1 upstream.
Patch fixes issue caused setting On-chip memory overflow bit in usb_sts register. The issue occurred because EP_CFG register was set twice before USB_STS.CFGSTS was set. Every write operation on EP_CFG.BUFFERING causes that controller increases internal counter holding the number of reserved on-chip buffers. First time this register was updated in function cdns3_ep_config before delegating SET_CONFIGURATION request to class driver and again it was updated when class wanted to enable endpoint. This patch fixes this issue by configuring endpoints enabled by class driver in cdns3_gadget_ep_enable and others just before status stage.
--- drivers/usb/cdns3/ep0.c | 65 +++++++++++++++------------- drivers/usb/cdns3/gadget.c | 102 +++++++++++++++++++++++++-------------------- drivers/usb/cdns3/gadget.h | 3 - 3 files changed, 94 insertions(+), 76 deletions(-)
drivers/usb/cdns3/ep0.c +35 -30
@@ -137,48 +137,36 @@ static int cdns3_req_ep0_set_configurati struct usb_ctrlrequest *ctrl_req) {enum usb_device_state device_state = priv_dev->gadget.state; -struct cdns3_endpoint *priv_ep;u32 config =le16_to_cpu (ctrl_req->wValue);int result =0 ; -int i;switch (device_state) {case USB_STATE_ADDRESS : -/* Configure non-control EPs */ -for (i =0 ; i <CDNS3_ENDPOINTS_MAX_COUNT ; i++) { - priv_ep = priv_dev->eps[i]; -if (!priv_ep) -continue ; - -if (priv_ep->flags &EP_CLAIMED ) -cdns3_ep_config (priv_ep); - } - result =cdns3_ep0_delegate_req (priv_dev, ctrl_req); -if (result) -return result; - -if (!config) { -cdns3_hw_reset_eps_config (priv_dev); -usb_gadget_set_state (&priv_dev->gadget, -USB_STATE_ADDRESS ); - } +if (result || !config) + goto reset_config;break ;case USB_STATE_CONFIGURED : result =cdns3_ep0_delegate_req (priv_dev, ctrl_req); +if (!config && !result) + goto reset_config; -if (!config && !result) { -cdns3_hw_reset_eps_config (priv_dev); -usb_gadget_set_state (&priv_dev->gadget, -USB_STATE_ADDRESS ); - }break ;default : - result = -EINVAL ; +return -EINVAL ; } +return 0 ; + +reset_config: +if (result !=USB_GADGET_DELAYED_STATUS ) +cdns3_hw_reset_eps_config (priv_dev); + +usb_gadget_set_state (&priv_dev->gadget, +USB_STATE_ADDRESS ); +return result; }
@@ -705,6 +693,7 @@ static int cdns3_gadget_ep0_queue(structunsigned long flags;int ret =0 ;u8 zlp =0 ; +int i;spin_lock_irqsave (&priv_dev->lock, flags);trace_cdns3_ep0_queue (priv_dev, request);
@@ -718,6 +707,17 @@ static int cdns3_gadget_ep0_queue(struct/* send STATUS stage. Should be called only for SET_CONFIGURATION */ if (priv_dev->ep0_stage ==CDNS3_STATUS_STAGE ) {cdns3_select_ep (priv_dev,0x00 ); + +/* +* Configure all non-control EPs which are not enabled by class driver +*/ +for (i =0 ; i <CDNS3_ENDPOINTS_MAX_COUNT ; i++) { + priv_ep = priv_dev->eps[i]; +if (priv_ep && priv_ep->flags &EP_CLAIMED && + !(priv_ep->flags &EP_ENABLED )) +cdns3_ep_config (priv_ep,0 ); + } +cdns3_set_hw_configuration (priv_dev);cdns3_ep0_complete_setup (priv_dev,0 ,1 ); request->actual =0 ;
@@ -803,6 +803,7 @@ void cdns3_ep0_config(struct cdns3_devicstruct cdns3_usb_regs __iomem *regs;struct cdns3_endpoint *priv_ep;u32 max_packet_size =64 ; +u32 ep_cfg; regs = priv_dev->regs;
@@ -834,8 +835,10 @@ void cdns3_ep0_config(struct cdns3_devic BIT(0) | BIT(16)); } -writel (EP_CFG_ENABLE |EP_CFG_MAXPKTSIZE (max_packet_size), - ®s->ep_cfg); + ep_cfg =EP_CFG_ENABLE |EP_CFG_MAXPKTSIZE (max_packet_size); + +if (!(priv_ep->flags &EP_CONFIGURED )) +writel (ep_cfg, ®s->ep_cfg);writel (EP_STS_EN_SETUPEN |EP_STS_EN_DESCMISEN |EP_STS_EN_TRBERREN , ®s->ep_sts_en);
@@ -843,8 +846,10 @@ void cdns3_ep0_config(struct cdns3_devic/* init ep in */ cdns3_select_ep (priv_dev,USB_DIR_IN ); -writel (EP_CFG_ENABLE |EP_CFG_MAXPKTSIZE (max_packet_size), - ®s->ep_cfg); +if (!(priv_ep->flags &EP_CONFIGURED )) +writel (ep_cfg, ®s->ep_cfg); + + priv_ep->flags |=EP_CONFIGURED ;writel (EP_STS_EN_SETUPEN |EP_STS_EN_TRBERREN , ®s->ep_sts_en);
drivers/usb/cdns3/gadget.c +57 -45
177 lines not on this page · raw message
drivers/usb/cdns3/gadget.h +2 -1
@@ -1154,6 +1154,7 @@ struct cdns3_endpoint {#define EP_QUIRK_EXTRA_BUF_DET BIT(12)#define EP_QUIRK_EXTRA_BUF_EN BIT(13)#define EP_TDLCHK_EN BIT(15) +#define EP_CONFIGURED BIT(16)u32 flags;struct cdns3_request *descmis_req;
@@ -1351,7 +1352,7 @@ void cdns3_gadget_giveback(struct cdns3_int cdns3_init_ep0 (struct cdns3_device *priv_dev,struct cdns3_endpoint *priv_ep);void cdns3_ep0_config (struct cdns3_device *priv_dev); -void cdns3_ep_config (struct cdns3_endpoint *priv_ep); +int cdns3_ep_config (struct cdns3_endpoint *priv_ep,bool enable);void cdns3_check_ep0_interrupt_proceed (struct cdns3_device *priv_dev,int dir);int __cdns3_gadget_wakeup (struct cdns3_device *priv_dev);
Greg Kroah-Hartman
maintainerPATCH 248/391 usb: cdc-acm: fix cooldown mechanism
In reply to Greg Kroah-HartmanFrom: Jerome Brunet <[email protected]>
commit 38203b8385bf6283537162bde7d499f830964711 upstream.
Commit a4e7279cd1d1 ("cdc-acm: introduce a cool down") is causing regression if there is some USB error, such as -EPROTO.
This has been reported on some samples of the Odroid-N2 using the Combee II Zibgee USB dongle.
Quoted 1 line
struct acm *acm =
container_of(work, struct acm, work)
is incorrect in case of a delayed work and causes warnings, usually from the workqueue:
Quoted 1 line
WARNING: CPU: 0 PID: 0 at kernel/workqueue.c:1474 __queue_work+0x480/0x528.
When this happens, USB eventually stops working completely after a while. Also the ACM_ERROR_DELAY bit is never set, so the cooldown mechanism previously introduced cannot be triggered and acm_submit_read_urb() is never called.
This changes makes the cdc-acm driver use a single delayed work, fixing the pointer arithmetic in acm_softint() and set the ACM_ERROR_DELAY when the cooldown mechanism appear to be needed.
--- drivers/usb/class/cdc-acm.c | 12 +++++------- drivers/usb/class/cdc-acm.h | 3 +-- 2 files changed, 6 insertions(+), 9 deletions(-)
drivers/usb/class/cdc-acm.c +5 -7
@@ -507,6 +507,7 @@ static void acm_read_bulk_callback(struc "%s - cooling babbling device\n", __func__);usb_mark_last_busy (acm->dev);set_bit (rb->index, &acm->urbs_in_error_delay); +set_bit (ACM_ERROR_DELAY , &acm->flags); cooldown = true;break ;default :
@@ -532,7 +533,7 @@ static void acm_read_bulk_callback(strucif (stopped || stalled || cooldown) {if (stalled) -schedule_work (&acm->work); +schedule_delayed_work (&acm->dwork,0 );else if (cooldown)schedule_delayed_work (&acm->dwork,HZ /2 );return ;
@@ -562,13 +563,13 @@ static void acm_write_bulk(struct urb *uacm_write_done (acm, wb);spin_unlock_irqrestore (&acm->write_lock, flags);set_bit (EVENT_TTY_WAKEUP , &acm->flags); -schedule_work (&acm->work); +schedule_delayed_work (&acm->dwork,0 ); }static void acm_softint (struct work_struct *work) {int i; - struct acm *acm = container_of(work, struct acm, work); + struct acm *acm = container_of(work, struct acm, dwork.work);if (test_bit (EVENT_RX_STALL , &acm->flags)) {smp_mb ();/* against acm_suspend() */
@@ -584,7 +585,7 @@ static void acm_softint(struct work_struif (test_and_clear_bit (ACM_ERROR_DELAY , &acm->flags)) {for (i =0 ; i < acm->rx_buflimit; i++)if (test_and_clear_bit (i, &acm->urbs_in_error_delay)) -acm_submit_read_urb (acm, i,GFP_NOIO ); +acm_submit_read_urb (acm, i,GFP_KERNEL ); }if (test_and_clear_bit (EVENT_TTY_WAKEUP , &acm->flags))
@@ -1364,7 +1365,6 @@ made_compressed_probe: acm->ctrlsize = ctrlsize; acm->readsize = readsize; acm->rx_buflimit = num_rx_buf; -INIT_WORK (&acm->work, acm_softint);INIT_DELAYED_WORK (&acm->dwork, acm_softint);init_waitqueue_head (&acm->wioctl);spin_lock_init (&acm->write_lock);
@@ -1574,7 +1574,6 @@ static void acm_disconnect(struct usb_in }acm_kill_urbs (acm); -cancel_work_sync (&acm->work);cancel_delayed_work_sync (&acm->dwork);tty_unregister_device (acm_tty_driver, acm->minor);
@@ -1617,7 +1616,6 @@ static int acm_suspend(struct usb_interfreturn 0 ;acm_kill_urbs (acm); -cancel_work_sync (&acm->work);cancel_delayed_work_sync (&acm->dwork); acm->urbs_in_error_delay =0 ;
drivers/usb/class/cdc-acm.h +1 -2
@@ -112,8 +112,7 @@ struct acm {# define ACM_ERROR_DELAY 3unsigned long urbs_in_error_delay;/* these need to be restarted after a delay */ struct usb_cdc_line_coding line;/* bits, stop, parity */ -struct work_struct work;/* work queue entry for various purposes*/ -struct delayed_work dwork;/* for cool downs needed in error recovery */ +struct delayed_work dwork;/* work queue entry for various purposes */ unsigned int ctrlin;/* input control lines (DCD, DSR, RI, break, overruns) */ unsigned int ctrlout;/* output control lines (DTR, RTS) */ struct async_icount iocount;/* counters for control line changes */
Greg Kroah-Hartman
maintainerPATCH 249/391 usb: typec: tcpm: reset hard_reset_count for any disconnect
In reply to Greg Kroah-HartmanFrom: Li Jun <[email protected]>
commit 2d9c6442a9c81f4f8dee678d0b3c183173ab1e2d upstream.
Current tcpm_detach() only reset hard_reset_count if port->attached is true, this may cause this counter clear is missed if the CC disconnect event is generated after tcpm_port_reset() is done by other events, e.g. VBUS off comes first before CC disconect for a power sink, in that case the first tcpm_detach() will only clear port->attached flag but leave hard_reset_count there because tcpm_port_is_disconnected() is still false, then later tcpm_detach() by CC disconnect will directly return due to port->attached is cleared, finally this will result tcpm will not try hard reset or error recovery for later attach.
ChiYuan reported this issue on his platform with below tcpm trace:
After power sink session setup after hard reset 2 times, detach from the power source and then attach:
[ 4848.046358] VBUS off [ 4848.046384] state change SNK_READY -> SNK_UNATTACHED [ 4848.050908] Setting voltage/current limit 0 mV 0 mA [ 4848.050936] polarity 0 [ 4848.052593] Requesting mux state 0, usb-role 0, orientation 0 [ 4848.053222] Start toggling [ 4848.086500] state change SNK_UNATTACHED -> TOGGLING [ 4848.089983] CC1: 0 -> 0, CC2: 3 -> 3 [state TOGGLING, polarity 0, connected] [ 4848.089993] state change TOGGLING -> SNK_ATTACH_WAIT [ 4848.090031] pending state change SNK_ATTACH_WAIT -> SNK_DEBOUNCED @200 ms [ 4848.141162] CC1: 0 -> 0, CC2: 3 -> 0 [state SNK_ATTACH_WAIT, polarity 0, disconnected] [ 4848.141170] state change SNK_ATTACH_WAIT -> SNK_ATTACH_WAIT [ 4848.141184] pending state change SNK_ATTACH_WAIT -> SNK_UNATTACHED @20 ms [ 4848.163156] state change SNK_ATTACH_WAIT -> SNK_UNATTACHED [delayed 20 ms] [ 4848.163162] Start toggling [ 4848.216918] CC1: 0 -> 0, CC2: 0 -> 3 [state TOGGLING, polarity 0, connected] [ 4848.216954] state change TOGGLING -> SNK_ATTACH_WAIT [ 4848.217080] pending state change SNK_ATTACH_WAIT -> SNK_DEBOUNCED @200 ms [ 4848.231771] CC1: 0 -> 0, CC2: 3 -> 0 [state SNK_ATTACH_WAIT, polarity 0, disconnected] [ 4848.231800] state change SNK_ATTACH_WAIT -> SNK_ATTACH_WAIT [ 4848.231857] pending state change SNK_ATTACH_WAIT -> SNK_UNATTACHED @20 ms [ 4848.256022] state change SNK_ATTACH_WAIT -> SNK_UNATTACHED [delayed20 ms] [ 4848.256049] Start toggling [ 4848.871148] VBUS on [ 4848.885324] CC1: 0 -> 0, CC2: 0 -> 3 [state TOGGLING, polarity 0, connected] [ 4848.885372] state change TOGGLING -> SNK_ATTACH_WAIT [ 4848.885548] pending state change SNK_ATTACH_WAIT -> SNK_DEBOUNCED @200 ms [ 4849.088240] state change SNK_ATTACH_WAIT -> SNK_DEBOUNCED [delayed200 ms] [ 4849.088284] state change SNK_DEBOUNCED -> SNK_ATTACHED [ 4849.088291] polarity 1 [ 4849.088769] Requesting mux state 1, usb-role 2, orientation 2 [ 4849.088895] state change SNK_ATTACHED -> SNK_STARTUP [ 4849.088907] state change SNK_STARTUP -> SNK_DISCOVERY [ 4849.088915] Setting voltage/current limit 5000 mV 0 mA [ 4849.088927] vbus=0 charge:=1 [ 4849.090505] state change SNK_DISCOVERY -> SNK_WAIT_CAPABILITIES [ 4849.090828] pending state change SNK_WAIT_CAPABILITIES -> SNK_READY @240 ms [ 4849.335878] state change SNK_WAIT_CAPABILITIES -> SNK_READY [delayed240 ms]
this patch fix this issue by clear hard_reset_count at any cases of cc disconnect, í.e. don't check port->attached flag.
--- drivers/usb/typec/tcpm/tcpm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/usb/typec/tcpm/tcpm.c +3 -3
@@ -2789,6 +2789,9 @@ static void tcpm_reset_port(struct tcpm_static void tcpm_detach (struct tcpm_port *port) { +if (tcpm_port_is_disconnected (port)) + port->hard_reset_count =0 ; +if (!port->attached)return ;
@@ -2797,9 +2800,6 @@ static void tcpm_detach(struct tcpm_port port->tcpc->set_bist_data (port->tcpc, false); } -if (tcpm_port_is_disconnected (port)) - port->hard_reset_count =0 ; -tcpm_reset_port (port); }
Greg Kroah-Hartman
maintainerPATCH 250/391 usb: host: fsl-mph-dr-of: check return of dma_set_mask()
In reply to Greg Kroah-HartmanFrom: Ran Wang <[email protected]>
commit 3cd54a618834430a26a648d880dd83d740f2ae30 upstream.
fsl_usb2_device_register() should stop init if dma_set_mask() return error.
--- drivers/usb/host/fsl-mph-dr-of.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
drivers/usb/host/fsl-mph-dr-of.c +6 -3
@@ -94,10 +94,13 @@ static struct platform_device *fsl_usb2_ pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask; -if (!pdev->dev.dma_mask) +if (!pdev->dev.dma_mask) { pdev->dev.dma_mask = &ofdev->dev.coherent_dma_mask; -else -dma_set_mask (&pdev->dev,DMA_BIT_MASK (32 )); + }else { + retval =dma_set_mask (&pdev->dev,DMA_BIT_MASK (32 )); +if (retval) + goto error; + } retval =platform_device_add_data (pdev, pdata,sizeof (*pdata));if (retval)
Greg Kroah-Hartman
maintainerPATCH 251/391 usbcore: Check both id_table and match() when both available
In reply to Greg Kroah-HartmanFrom: Bastien Nocera <[email protected]>
commit 0942d59b0af46511d59dbf5bd69ec4a64d1a854c upstream.
From: Bastien Nocera <[email protected]>
When a USB device driver has both an id_table and a match() function, make sure to check both to find a match, first matching the id_table, then checking the match() function.
This makes it possible to have module autoloading done through the id_table when devices are plugged in, before checking for further device eligibility in the match() function.
--- drivers/usb/core/driver.c | 30 +++++++++++++++++++++--------- drivers/usb/core/generic.c | 4 +--- drivers/usb/core/usb.h | 2 ++ 3 files changed, 24 insertions(+), 12 deletions(-)
drivers/usb/core/driver.c +21 -9
@@ -839,6 +839,22 @@ const struct usb_device_id *usb_device_mreturn NULL ; } +bool usb_driver_applicable (struct usb_device *udev, +struct usb_device_driver *udrv) +{ +if (udrv->id_table && udrv->match) +return usb_device_match_id (udev, udrv->id_table) !=NULL && + udrv->match (udev); + +if (udrv->id_table) +return usb_device_match_id (udev, udrv->id_table) !=NULL ; + +if (udrv->match) +return udrv->match (udev); + +return false; +} +static int usb_device_match (struct device *dev,struct device_driver *drv) {/* devices and interfaces are handled separately */
@@ -853,17 +869,14 @@ static int usb_device_match(struct devic udev =to_usb_device (dev); udrv =to_usb_device_driver (drv); -if (udrv->id_table) -return usb_device_match_id (udev, udrv->id_table) !=NULL ; - -if (udrv->match) -return udrv->match (udev); -/* If the device driver under consideration does not have a * id_table or a match function, then let the driver's probe * function decide. */ -return 1 ; +if (!udrv->id_table && !udrv->match) +return 1 ; + +return usb_driver_applicable (udev, udrv); }else if (is_usb_interface (dev)) {struct usb_interface *intf;
@@ -941,8 +954,7 @@ static int __usb_bus_reprobe_drivers(strreturn 0 ; udev =to_usb_device (dev); -if (usb_device_match_id (udev, new_udriver->id_table) ==NULL && - (!new_udriver->match || new_udriver->match (udev) ==0 )) +if (!usb_driver_applicable (udev, new_udriver))return 0 ; ret =device_reprobe (dev);
drivers/usb/core/generic.c +1 -3
@@ -205,9 +205,7 @@ static int __check_usb_generic(struct de udrv =to_usb_device_driver (drv);if (udrv == &usb_generic_driver)return 0 ; -if (usb_device_match_id (udev, udrv->id_table) !=NULL ) -return 1 ; -return (udrv->match && udrv->match (udev)); +return usb_driver_applicable (udev, udrv); }static bool usb_generic_driver_match (struct usb_device *udev)
drivers/usb/core/usb.h +2 -0
@@ -74,6 +74,8 @@ extern int usb_match_device(struct usb_d const struct usb_device_id *id);extern const struct usb_device_id *usb_device_match_id (struct usb_device *udev,const struct usb_device_id *id); +extern bool usb_driver_applicable (struct usb_device *udev, +struct usb_device_driver *udrv);extern void usb_forced_unbind_intf (struct usb_interface *intf);extern void usb_unbind_and_rebind_marked_interfaces (struct usb_device *udev);
Greg Kroah-Hartman
maintainerPATCH 252/391 USB: apple-mfi-fastcharge: dont probe unhandled devices
In reply to Greg Kroah-HartmanFrom: Bastien Nocera <[email protected]>
commit 0cb686692fd200db12dcfb8231e793c1c98aec41 upstream.
From: Bastien Nocera <[email protected]>
Contrary to the comment above the id table, we didn't implement a match function. This meant that every single Apple device that was already plugged in to the computer would have its device driver reprobed when the apple-mfi-fastcharge driver was loaded, eg. the SD card reader could be reprobed when the apple-mfi-fastcharge after pivoting root during boot up and the module became available.
Make sure that the driver probe isn't being run for unsupported devices by adding a match function that checks the product ID, in addition to the id_table checking the vendor ID.
--- drivers/usb/misc/apple-mfi-fastcharge.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
drivers/usb/misc/apple-mfi-fastcharge.c +12 -5
@@ -163,17 +163,23 @@ static const struct power_supply_desc ap .property_is_writeable = apple_mfi_fc_property_is_writeable }; +static bool mfi_fc_match (struct usb_device *udev) +{ +int idProduct; + + idProduct =le16_to_cpu (udev->descriptor.idProduct); +/* See comment above mfi_fc_id_table[] */ +return (idProduct >=0x1200 && idProduct <=0x12ff ); +} +static int mfi_fc_probe (struct usb_device *udev) {struct power_supply_config battery_cfg = {};struct mfi_device *mfi =NULL ; -int err, idProduct; +int err; - idProduct =le16_to_cpu (udev->descriptor.idProduct); -/* See comment above mfi_fc_id_table[] */ -if (idProduct <0x1200 || idProduct >0x12ff ) { +if (!mfi_fc_match (udev))return -ENODEV ; - } mfi =kzalloc (sizeof (struct mfi_device ),GFP_KERNEL );if (!mfi) {
@@ -220,6 +226,7 @@ static struct usb_device_driver mfi_fc_d .probe = mfi_fc_probe, .disconnect = mfi_fc_disconnect, .id_table = mfi_fc_id_table, + .match = mfi_fc_match, .generic_subclass = 1, };
Greg Kroah-Hartman
maintainerPATCH 253/391 drm/i915: Force VTd workarounds when running as a guest OS
In reply to Greg Kroah-HartmanFrom: Chris Wilson <[email protected]>
commit 8195400f7ea95399f721ad21f4d663a62c65036f upstream.
If i915.ko is being used as a passthrough device, it does not know if the host is using intel_iommu. Mixing the iommu and gfx causes a few issues (such as scanout overfetch) which we need to workaround inside the driver, so if we detect we are running under a hypervisor, also assume the device access is being virtualised.
--- drivers/gpu/drm/i915/i915_drv.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/i915_drv.h +5 -1
@@ -33,6 +33,8 @@#include <uapi/drm/i915_drm.h> #include <uapi/drm/drm_fourcc.h> +#include <asm/hypervisor.h> +#include <linux/io-mapping.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h>
@@ -1716,7 +1718,9 @@ static inline bool intel_vtd_active(voidif (intel_iommu_gfx_mapped)return true;#endif -return false; + +/* Running as a guest, we assume the host is enforcing VT'd */ +return !hypervisor_is_type (X86_HYPER_NATIVE ); }static inline bool intel_scanout_needs_vtd_wa (struct drm_i915_private *dev_priv)
Greg Kroah-Hartman
maintainerPATCH 254/391 vt: keyboard, simplify vt_kdgkbsent
In reply to Greg Kroah-HartmanFrom: Jiri Slaby <[email protected]>
commit 6ca03f90527e499dd5e32d6522909e2ad390896b upstream.
Use 'strlen' of the string, add one for NUL terminator and simply do 'copy_to_user' instead of the explicit 'for' loop. This makes the KDGKBSENT case more compact.
The only thing we need to take care about is NULL 'func_table[i]'. Use an empty string in that case.
The original check for overflow could never trigger as the func_buf strings are always shorter or equal to 'struct kbsentry's.
--- drivers/tty/vt/keyboard.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-)
drivers/tty/vt/keyboard.c +9 -19
@@ -1995,9 +1995,7 @@ out:int vt_do_kdgkb_ioctl (int cmd,struct kbsentry __user *user_kdgkb,int perm) {struct kbsentry *kbs; -char *p;u_char *q; -u_char __user *up;int sz, fnw_sz;int delta;char *first_free, *fj, *fnw;
@@ -2023,23 +2021,15 @@ int vt_do_kdgkb_ioctl(int cmd, struct kb i =array_index_nospec (kbs->kb_func,MAX_NR_FUNC );switch (cmd) { -case KDGKBSENT : - sz =sizeof (kbs->kb_string) -1 ;/* sz should have been -a struct member */ - up = user_kdgkb->kb_string; - p = func_table[i]; -if (p) -for ( ; *p && sz; p++, sz--) -if (put_user (*p, up++)) { - ret = -EFAULT ; - goto reterr; - } -if (put_user ('\0' , up)) { - ret = -EFAULT ; - goto reterr; - } -kfree (kbs); -return ((p && *p) ? -EOVERFLOW :0 ); +case KDGKBSENT : { +/* size should have been a struct member */ +unsigned char *from = func_table[i] ? :"" ; + + ret =copy_to_user (user_kdgkb->kb_string, from, +strlen (from) +1 ) ? -EFAULT :0 ; + + goto reterr; + }case KDSKBSENT :if (!perm) { ret = -EPERM ;
Greg Kroah-Hartman
maintainerPATCH 255/391 vt: keyboard, extend func_buf_lock to readers
In reply to Greg Kroah-HartmanFrom: Jiri Slaby <[email protected]>
commit 82e61c3909db51d91b9d3e2071557b6435018b80 upstream.
Both read-side users of func_table/func_buf need locking. Without that, one can easily confuse the code by repeatedly setting altering strings like:
while (1)
for (a = 0; a < 2; a++) {
struct kbsentry kbs = {};
strcpy((char *)kbs.kb_string, a ? ".\n" : "88888\n");
ioctl(fd, KDSKBSENT, &kbs);
}When that program runs, one can get unexpected output by holding F1 (note the unxpected period on the last line):
.
88888
.8888
So protect all accesses to 'func_table' (and func_buf) by preexisting 'func_buf_lock'.
It is easy in 'k_fn' handler as 'puts_queue' is expected not to sleep. On the other hand, KDGKBSENT needs a local (atomic) copy of the string because copy_to_user can sleep. Use already allocated, but unused 'kbs->kb_string' for that purpose.
Note that the program above needs at least CAP_SYS_TTY_CONFIG.
This depends on the previous patch and on the func_buf_lock lock added in commit 46ca3f735f34 (tty/vt: fix write/write race in ioctl(KDSKBSENT) handler) in 5.2.
Likely fixes CVE-2020-25656.
--- drivers/tty/vt/keyboard.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
drivers/tty/vt/keyboard.c +13 -4
@@ -743,8 +743,13 @@ static void k_fn(struct vc_data *vc, unsreturn ;if ((unsigned )value <ARRAY_SIZE (func_table)) { +unsigned long flags; + +spin_lock_irqsave (&func_buf_lock, flags);if (func_table[value])puts_queue (vc, func_table[value]); +spin_unlock_irqrestore (&func_buf_lock, flags); + }else pr_err ("k_fn called with value=%d\n" , value); }
@@ -1991,7 +1996,7 @@ out:#undef s#undef v -/* FIXME: This one needs untangling and locking */ +/* FIXME: This one needs untangling */ int vt_do_kdgkb_ioctl (int cmd,struct kbsentry __user *user_kdgkb,int perm) {struct kbsentry *kbs;
@@ -2023,10 +2028,14 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbswitch (cmd) {case KDGKBSENT : {/* size should have been a struct member */ -unsigned char *from = func_table[i] ? :"" ; +ssize_t len =sizeof (user_kdgkb->kb_string); + +spin_lock_irqsave (&func_buf_lock, flags); + len =strlcpy (kbs->kb_string, func_table[i] ? :"" , len); +spin_unlock_irqrestore (&func_buf_lock, flags); - ret =copy_to_user (user_kdgkb->kb_string, from, -strlen (from) +1 ) ? -EFAULT :0 ; + ret =copy_to_user (user_kdgkb->kb_string, kbs->kb_string, + len +1 ) ? -EFAULT :0 ; goto reterr; }
Greg Kroah-Hartman
maintainerPATCH 256/391 vt_ioctl: fix GIO_UNIMAP regression
In reply to Greg Kroah-HartmanFrom: Jiri Slaby <[email protected]>
commit d54654790302ccaa72589380dce060d376ef8716 upstream.
In commit 5ba127878722, we shuffled with the check of 'perm'. But my brain somehow inverted the condition in 'do_unimap_ioctl' (I thought it is ||, not &&), so GIO_UNIMAP stopped working completely.
Move the 'perm' checks back to do_unimap_ioctl and do them right again. In fact, this reverts this part of code to the pre-5ba127878722 state. Except 'perm' is now a bool.
--- drivers/tty/vt/vt_ioctl.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
drivers/tty/vt/vt_ioctl.c +5 -6
@@ -550,7 +550,7 @@ static int vt_io_fontreset(struct consol }static inline int do_unimap_ioctl (int cmd,struct unimapdesc __user *user_ud, -struct vc_data *vc) +bool perm,struct vc_data *vc) {struct unimapdesc tmp;
@@ -558,9 +558,11 @@ static inline int do_unimap_ioctl(int cmreturn -EFAULT ;switch (cmd) {case PIO_UNIMAP : +if (!perm) +return -EPERM ;return con_set_unimap (vc, tmp.entry_ct, tmp.entries);case GIO_UNIMAP : -if (fg_console != vc->vc_num) +if (!perm && fg_console != vc->vc_num)return -EPERM ;return con_get_unimap (vc, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries);
@@ -640,10 +642,7 @@ static int vt_io_ioctl(struct vc_data *vcase PIO_UNIMAP :case GIO_UNIMAP : -if (!perm) -return -EPERM ; - -return do_unimap_ioctl (cmd, up, vc); +return do_unimap_ioctl (cmd, up, perm, vc);default :return -ENOIOCTLCMD ;
Greg Kroah-Hartman
maintainerPATCH 257/391 HID: wacom: Avoid entering wacom_wac_pen_report for pad / battery
In reply to Greg Kroah-HartmanFrom: Jason Gerecke <[email protected]>
commit d9216d753b2b1406b801243b12aaf00a5ce5b861 upstream.
It has recently been reported that the "heartbeat" report from devices like the 2nd-gen Intuos Pro (PTH-460, PTH-660, PTH-860) or the 2nd-gen Bluetooth-enabled Intuos tablets (CTL-4100WL, CTL-6100WL) can cause the driver to send a spurious BTN_TOUCH=0 once per second in the middle of drawing. This can result in broken lines while drawing on Chrome OS.
The source of the issue has been traced back to a change which modified the driver to only call wacom_wac_pad_report() once per report instead of once per collection. As part of this change, pad-handling code was removed from wacom_wac_collection() under the assumption that the WACOM_PEN_FIELD and WACOM_TOUCH_FIELD checks would not be satisfied when a pad or battery collection was being processed.
To be clear, the macros WACOM_PAD_FIELD and WACOM_PEN_FIELD do not currently check exclusive conditions. In fact, most "pad" fields will also appear to be "pen" fields simply due to their presence inside of a Digitizer application collection. Because of this, the removal of the check from wacom_wac_collection() just causes pad / battery collections to instead trigger a call to wacom_wac_pen_report() instead. The pen report function in turn resets the tip switch state just prior to exiting, resulting in the observed BTN_TOUCH=0 symptom.
To correct this, we restore a version of the WACOM_PAD_FIELD check in wacom_wac_collection() and return early. This effectively prevents pad / battery collections from being reported until the very end of the report as originally intended.
--- drivers/hid/wacom_wac.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/hid/wacom_wac.c +3 -1
@@ -2773,7 +2773,9 @@ static int wacom_wac_collection(struct hif (report->type !=HID_INPUT_REPORT )return -1 ; -if (WACOM_PEN_FIELD (field) && wacom->wacom_wac.pen_input) +if (WACOM_PAD_FIELD (field)) +return 0 ; +else if (WACOM_PEN_FIELD (field) && wacom->wacom_wac.pen_input)wacom_wac_pen_report (hdev, report);else if (WACOM_FINGER_FIELD (field) && wacom->wacom_wac.touch_input)wacom_wac_finger_report (hdev, report);
Greg Kroah-Hartman
maintainerPATCH 258/391 x86/mce: Allow for copy_mc_fragile symbol checksum to be generated
In reply to Greg Kroah-HartmanFrom: Borislav Petkov <[email protected]>
commit b3149ffcdb31a8eb854cc442a389ae0b539bf28a upstream.
Add asm/mce.h to asm/asm-prototypes.h so that that asm symbol's checksum can be generated in order to support CONFIG_MODVERSIONS with it and fix:
WARNING: modpost: EXPORT symbol "copy_mc_fragile" [vmlinux] version \
generation failed, symbol will not be versioned.
For reference see:
4efca4ed05cb ("kbuild: modversions for EXPORT_SYMBOL() for asm") 334bb7738764 ("x86/kbuild: enable modversions for symbols exported from asm")
--- arch/x86/include/asm/asm-prototypes.h | 1 + 1 file changed, 1 insertion(+)
arch/x86/include/asm/asm-prototypes.h +1 -0
@@ -5,6 +5,7 @@#include <asm/string.h> #include <asm/page.h> #include <asm/checksum.h> +#include <asm/mce.h> #include <asm-generic/asm-prototypes.h>
Greg Kroah-Hartman
maintainerPATCH 259/391 tty: serial: 21285: fix lockup on open
In reply to Greg Kroah-HartmanFrom: Russell King <[email protected]>
commit 82776f6c75a90e1d2103e689b84a689de8f1aa02 upstream.
Commit 293f89959483 ("tty: serial: 21285: stop using the unused[] variable from struct uart_port") introduced a bug which stops the transmit interrupt being disabled when there are no characters to transmit - disabling the transmit interrupt at the interrupt controller is the only way to stop an interrupt storm. If this interrupt is not disabled when there are no transmit characters, we end up with an interrupt storm which prevents the machine making forward progress.
--- drivers/tty/serial/21285.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/tty/serial/21285.c +6 -6
@@ -50,25 +50,25 @@ static const char serial21285_name[] = "static bool is_enabled (struct uart_port *port,int bit) { -unsigned long private_data = (unsigned long )port->private_data; +unsigned long *private_data = (unsigned long *)&port->private_data; -if (test_bit (bit, &private_data)) +if (test_bit (bit, private_data))return true;return false; }static void enable (struct uart_port *port,int bit) { -unsigned long private_data = (unsigned long )port->private_data; +unsigned long *private_data = (unsigned long *)&port->private_data; -set_bit (bit, &private_data); +set_bit (bit, private_data); }static void disable (struct uart_port *port,int bit) { -unsigned long private_data = (unsigned long )port->private_data; +unsigned long *private_data = (unsigned long *)&port->private_data; -clear_bit (bit, &private_data); +clear_bit (bit, private_data); }#define is_tx_enabled (port) is_enabled(port, tx_enabled_bit)
Greg Kroah-Hartman
maintainerPATCH 260/391 tty: serial: fsl_lpuart: LS1021A has a FIFO size of 16 words, like LS1028A
In reply to Greg Kroah-HartmanFrom: Vladimir Oltean <[email protected]>
commit c97f2a6fb3dfbfbbc88edc8ea62ef2b944e18849 upstream.
Prior to the commit that this one fixes, the FIFO size was derived from the read-only register LPUARTx_FIFO[TXFIFOSIZE] using the following formula:
TX FIFO size = 2 ^ (LPUARTx_FIFO[TXFIFOSIZE] - 1)
The documentation for LS1021A is a mess. Under chapter 26.1.3 LS1021A LPUART module special consideration, it mentions TXFIFO_SZ and RXFIFO_SZ being equal to 4, and in the register description for LPUARTx_FIFO, it shows the out-of-reset value of TXFIFOSIZE and RXFIFOSIZE fields as "011", even though these registers read as "101" in reality.
And when LPUART on LS1021A was working, the "101" value did correspond to "16 datawords", by applying the formula above, even though the documentation is wrong again (!!!!) and says that "101" means 64 datawords (hint: it doesn't).
So the "new" formula created by commit f77ebb241ce0 has all the premises of being wrong for LS1021A, because it relied only on false data and no actual experimentation.
Interestingly, in commit c2f448cff22a ("tty: serial: fsl_lpuart: add LS1028A support"), Michael Walle applied a workaround to this by manually setting the FIFO widths for LS1028A. It looks like the same values are used by LS1021A as well, in fact.
When the driver thinks that it has a deeper FIFO than it really has, getty (user space) output gets truncated.
Many thanks to Michael for pointing out where to look.
Reviewed-by:Fugang Duan <[email protected]>
--- drivers/tty/serial/fsl_lpuart.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/tty/serial/fsl_lpuart.c +7 -6
@@ -314,9 +314,10 @@ MODULE_DEVICE_TABLE(of, lpuart_dt_ids);/* Forward declare this for the dma callbacks*/ static void lpuart_dma_tx_complete (void *arg); -static inline bool is_ls1028a_lpuart (struct lpuart_port *sport) +static inline bool is_layerscape_lpuart (struct lpuart_port *sport) { -return sport->devtype ==LS1028A_LPUART ; +return (sport->devtype ==LS1021A_LPUART || + sport->devtype ==LS1028A_LPUART ); }static inline bool is_imx8qxp_lpuart (struct lpuart_port *sport)
@@ -1644,11 +1645,11 @@ static int lpuart32_startup(struct uart_ UARTFIFO_FIFOSIZE_MASK);/* -* The LS1028A has a fixed length of 16 words. Although it supports the -* RX/TXSIZE fields their encoding is different. Eg the reference manual -* states 0b101 is 16 words. +* The LS1021A and LS1028A have a fixed FIFO depth of 16 words. +* Although they support the RX/TXSIZE fields, their encoding is +* different. Eg the reference manual states 0b101 is 16 words. */ -if (is_ls1028a_lpuart (sport)) { +if (is_layerscape_lpuart (sport)) { sport->rxfifo_size =16 ; sport->txfifo_size =16 ; sport->port.fifosize = sport->txfifo_size;
Greg Kroah-Hartman
maintainerPATCH 261/391 tracing: Fix race in trace_open and buffer resize call
In reply to Greg Kroah-HartmanFrom: Gaurav Kohli <[email protected]>
commit bbeb97464eefc65f506084fd9f18f21653e01137 upstream.
Below race can come, if trace_open and resize of
cpu buffer is running parallely on different cpus
CPUX CPUY
ring_buffer_resize atomic_read(&buffer->resize_disabled)
tracing_opentracing_reset_online_cpus ring_buffer_reset_cpurb_reset_cpu
rb_update_pages remove/insert pages
resetting pointer
This race can cause data abort or some times infinte loop in rb_remove_pages and rb_insert_pages while checking pages for sanity.
Take buffer lock to fix this.
--- kernel/trace/ring_buffer.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
kernel/trace/ring_buffer.c +10 -0
@@ -4866,6 +4866,9 @@ void ring_buffer_reset_cpu(struct trace_if (!cpumask_test_cpu (cpu, buffer->cpumask))return ; +/* prevent another thread from changing buffer sizes */ +mutex_lock (&buffer->mutex); +atomic_inc (&cpu_buffer->resize_disabled);atomic_inc (&cpu_buffer->record_disabled);
@@ -4876,6 +4879,8 @@ void ring_buffer_reset_cpu(struct trace_atomic_dec (&cpu_buffer->record_disabled);atomic_dec (&cpu_buffer->resize_disabled); + +mutex_unlock (&buffer->mutex); }EXPORT_SYMBOL_GPL (ring_buffer_reset_cpu);
@@ -4889,6 +4894,9 @@ void ring_buffer_reset_online_cpus(strucstruct ring_buffer_per_cpu *cpu_buffer;int cpu; +/* prevent another thread from changing buffer sizes */ +mutex_lock (&buffer->mutex); +for_each_online_buffer_cpu (buffer, cpu) { cpu_buffer = buffer->buffers[cpu];
@@ -4907,6 +4915,8 @@ void ring_buffer_reset_online_cpus(strucatomic_dec (&cpu_buffer->record_disabled);atomic_dec (&cpu_buffer->resize_disabled); } + +mutex_unlock (&buffer->mutex); }/**
Greg Kroah-Hartman
maintainerPATCH 262/391 Revert "vhost-vdpa: fix page pinning leakage in error path"
In reply to Greg Kroah-HartmanFrom: Michael S. Tsirkin <[email protected]>
commit 5e1a3149eec8675c2767cc465903f5e4829de5b0 upstream.
This reverts commit 7ed9e3d97c32d969caded2dfb6e67c1a2cc5a0b1.
The patch creates a DoS risk since it can result in a high order memory allocation.
--- drivers/vhost/vdpa.c | 117 ++++++++++++++++++++------------------------------- 1 file changed, 47 insertions(+), 70 deletions(-)
drivers/vhost/vdpa.c +47 -70
@@ -595,19 +595,21 @@ static int vhost_vdpa_process_iotlb_updastruct vhost_dev *dev = &v->vdev;struct vhost_iotlb *iotlb = dev->iotlb;struct page **page_list; -struct vm_area_struct **vmas; +unsigned long list_size =PAGE_SIZE /sizeof (struct page *);unsigned int gup_flags =FOLL_LONGTERM ; -unsigned long map_pfn, last_pfn =0 ; -unsigned long npages, lock_limit; -unsigned long i, nmap =0 ; +unsigned long npages, cur_base, map_pfn, last_pfn =0 ; +unsigned long locked, lock_limit, pinned, i;u64 iova = msg->iova; -long pinned;int ret =0 ;if (vhost_iotlb_itree_first (iotlb, msg->iova, msg->iova + msg->size -1 ))return -EEXIST ; + page_list = (struct page **)__get_free_page (GFP_KERNEL ); +if (!page_list) +return -ENOMEM ; +if (msg->perm &VHOST_ACCESS_WO ) gup_flags |=FOLL_WRITE ;
@@ -615,86 +617,61 @@ static int vhost_vdpa_process_iotlb_updaif (!npages)return -EINVAL ; - page_list =kvmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); - vmas =kvmalloc_array (npages,sizeof (struct vm_area_struct *), -GFP_KERNEL ); -if (!page_list || !vmas) { - ret = -ENOMEM ; - goto free; - } -mmap_read_lock (dev->mm); + locked =atomic64_add_return (npages, &dev->mm->pinned_vm); lock_limit =rlimit (RLIMIT_MEMLOCK ) >>PAGE_SHIFT ; -if (npages +atomic64_read (&dev->mm->pinned_vm) > lock_limit) { - ret = -ENOMEM ; - goto unlock; - } - pinned =pin_user_pages (msg->uaddr &PAGE_MASK , npages, gup_flags, - page_list, vmas); -if (npages != pinned) { -if (pinned <0 ) { - ret = pinned; - }else { -unpin_user_pages (page_list, pinned); - ret = -ENOMEM ; - } - goto unlock; +if (locked > lock_limit) { + ret = -ENOMEM ; + goto out; } + cur_base = msg->uaddr &PAGE_MASK ; iova &=PAGE_MASK ; - map_pfn =page_to_pfn (page_list[0 ]); -/* One more iteration to avoid extra vdpa_map() call out of loop. */ -for (i =0 ; i <= npages; i++) { -unsigned long this_pfn; -u64 csize; - -/* The last chunk may have no valid PFN next to it */ - this_pfn = i < npages ?page_to_pfn (page_list[i]) :-1UL ; - -if (last_pfn && (this_pfn ==-1UL || - this_pfn != last_pfn +1 )) { -/* Pin a contiguous chunk of memory */ - csize = last_pfn - map_pfn +1 ; - ret =vhost_vdpa_map (v, iova, csize <<PAGE_SHIFT , - map_pfn <<PAGE_SHIFT , - msg->perm); -if (ret) { -/* -* Unpin the rest chunks of memory on the -* flight with no corresponding vdpa_map() -* calls having been made yet. On the other -* hand, vdpa_unmap() in the failure path -* is in charge of accounting the number of -* pinned pages for its own. -* This asymmetrical pattern of accounting -* is for efficiency to pin all pages at -* once, while there is no other callsite -* of vdpa_map() than here above. -*/ -unpin_user_pages (&page_list[nmap], - npages - nmap); - goto out; +while (npages) { + pinned = min_t(unsigned long, npages, list_size); + ret =pin_user_pages (cur_base, pinned, + gup_flags, page_list,NULL ); +if (ret != pinned) + goto out; + +if (!last_pfn) + map_pfn =page_to_pfn (page_list[0 ]); + +for (i =0 ; i < ret; i++) { +unsigned long this_pfn =page_to_pfn (page_list[i]); +u64 csize; + +if (last_pfn && (this_pfn != last_pfn +1 )) { +/* Pin a contiguous chunk of memory */ + csize = (last_pfn - map_pfn +1 ) <<PAGE_SHIFT ; +if (vhost_vdpa_map (v, iova, csize, + map_pfn <<PAGE_SHIFT , + msg->perm)) + goto out; + map_pfn = this_pfn; + iova += csize; } -atomic64_add (csize, &dev->mm->pinned_vm); - nmap += csize; - iova += csize <<PAGE_SHIFT ; - map_pfn = this_pfn; + + last_pfn = this_pfn; } - last_pfn = this_pfn; + + cur_base += ret <<PAGE_SHIFT ; + npages -= ret; } -WARN_ON (nmap != npages); +/* Pin the rest chunk */ + ret =vhost_vdpa_map (v, iova, (last_pfn - map_pfn +1 ) <<PAGE_SHIFT , + map_pfn <<PAGE_SHIFT , msg->perm); out: -if (ret) +if (ret) {vhost_vdpa_unmap (v, msg->iova, msg->size); -unlock: +atomic64_sub (npages, &dev->mm->pinned_vm); + }mmap_read_unlock (dev->mm); -free: -kvfree (vmas); -kvfree (page_list); +free_page ((unsigned long )page_list);return ret; }
Greg Kroah-Hartman
maintainerPATCH 263/391 powerpc: Fix random segfault when freeing hugetlb range
In reply to Greg Kroah-HartmanFrom: Christophe Leroy <[email protected]>
commit 542db12a9c42d1ce70c45091765e02f74c129f43 upstream.
The following random segfault is observed from time to time with map_hugetlb selftest:
root@localhost:~# ./map_hugetlb 1 19 524288 kB hugepages Mapping 1 Mbytes Segmentation fault
[ 31.219972] map_hugetlb[365]: segfault (11) at 117 nip 77974f8c lr 779a6834 code 1 in ld-2.23.so[77966000+21000] [ 31.220192] map_hugetlb[365]: code: 9421ffc0 480318d1 93410028 90010044 9361002c 93810030 93a10034 93c10038 [ 31.220307] map_hugetlb[365]: code: 93e1003c 93210024 8123007c 81430038 <80e90004> 814a0004 7f443a14 813a0004 [ 31.221911] BUG: Bad rss-counter state mm:(ptrval) type:MM_FILEPAGES val:33 [ 31.229362] BUG: Bad rss-counter state mm:(ptrval) type:MM_ANONPAGES val:5
This fault is due to hugetlb_free_pgd_range() freeing page tables that are also used by regular pages.
As explain in the comment at the beginning of hugetlb_free_pgd_range(), the verification done in free_pgd_range() on floor and ceiling is not done here, which means hugetlb_free_pte_range() can free outside the expected range.
As the verification cannot be done in hugetlb_free_pgd_range(), it must be done in hugetlb_free_pte_range().
--- arch/powerpc/mm/hugetlbpage.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
arch/powerpc/mm/hugetlbpage.c +16 -2
@@ -330,10 +330,24 @@ static void free_hugepd_range(struct mmu get_hugepd_cache_index(pdshift - shift)); } -static void hugetlb_free_pte_range (struct mmu_gather *tlb,pmd_t *pmd,unsigned long addr) +static void hugetlb_free_pte_range (struct mmu_gather *tlb,pmd_t *pmd, +unsigned long addr,unsigned long end, +unsigned long floor,unsigned long ceiling) { +unsigned long start = addr;pgtable_t token =pmd_pgtable (*pmd); + start &=PMD_MASK ; +if (start < floor) +return ; +if (ceiling) { + ceiling &=PMD_MASK ; +if (!ceiling) +return ; + } +if (end -1 > ceiling -1 ) +return ; +pmd_clear (pmd);pte_free_tlb (tlb, token, addr);mm_dec_nr_ptes (tlb->mm);
@@ -363,7 +377,7 @@ static void hugetlb_free_pmd_range(struc*/ WARN_ON (!IS_ENABLED (CONFIG_PPC_8xx)); -hugetlb_free_pte_range (tlb, pmd, addr); +hugetlb_free_pte_range (tlb, pmd, addr, end, floor, ceiling);continue ; }
Greg Kroah-Hartman
maintainerPATCH 264/391 udf: Fix memory leak when mounting
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
commit a7be300de800e755714c71103ae4a0d205e41e99 upstream.
udf_process_sequence() allocates temporary array for processing partition descriptors on volume which it fails to free. Free the array when it is not needed anymore.
--- fs/udf/super.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-)
fs/udf/super.c +13 -8
@@ -1704,7 +1704,8 @@ static noinline int udf_process_sequence"Pointers (max %u supported)\n" , UDF_MAX_TD_NESTING);brelse (bh); -return -EIO ; + ret = -EIO ; + goto out; } vdp = (struct volDescPtr *)bh->b_data;
@@ -1724,7 +1725,8 @@ static noinline int udf_process_sequence curr =get_volume_descriptor_record (ident, bh, &data);if (IS_ERR (curr)) {brelse (bh); -return PTR_ERR (curr); + ret =PTR_ERR (curr); + goto out; }/* Descriptor we don't care about? */ if (!curr)
@@ -1746,28 +1748,31 @@ static noinline int udf_process_sequence*/ if (!data.vds[VDS_POS_PRIMARY_VOL_DESC ].block) {udf_err (sb,"Primary Volume Descriptor not found!\n" ); -return -EAGAIN ; + ret = -EAGAIN ; + goto out; } ret =udf_load_pvoldesc (sb, data.vds[VDS_POS_PRIMARY_VOL_DESC ].block);if (ret <0 ) -return ret; + goto out;if (data.vds[VDS_POS_LOGICAL_VOL_DESC ].block) { ret =udf_load_logicalvol (sb, data.vds[VDS_POS_LOGICAL_VOL_DESC ].block, fileset);if (ret <0 ) -return ret; + goto out; }/* Now handle prevailing Partition Descriptors */ for (i =0 ; i < data.num_part_descs; i++) { ret =udf_load_partdesc (sb, data.part_descs_loc[i].rec.block);if (ret <0 ) -return ret; + goto out; } - -return 0 ; + ret =0 ; +out: +kfree (data.part_descs_loc); +return ret; }/*
Greg Kroah-Hartman
maintainerPATCH 265/391 dmaengine: dma-jz4780: Fix race in jz4780_dma_tx_status
In reply to Greg Kroah-HartmanFrom: Paul Cercueil <[email protected]>
commit baf6fd97b16ea8f981b8a8b04039596f32fc2972 upstream.
The jz4780_dma_tx_status() function would check if a channel's cookie state was set to 'completed', and if not, it would enter the critical section. However, in that time frame, the jz4780_dma_chan_irq() function was able to set the cookie to 'completed', and clear the jzchan->vchan pointer, which was deferenced in the critical section of the first function.
Fix this race by checking the channel's cookie state after entering the critical function and not before.
--- drivers/dma/dma-jz4780.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/dma/dma-jz4780.c +4 -3
@@ -639,11 +639,11 @@ static enum dma_status jz4780_dma_tx_staunsigned long flags;unsigned long residue =0 ; +spin_lock_irqsave (&jzchan->vchan.lock, flags); + status =dma_cookie_status (chan, cookie, txstate);if ((status ==DMA_COMPLETE ) || (txstate ==NULL )) -return status; - -spin_lock_irqsave (&jzchan->vchan.lock, flags); + goto out_unlock_irqrestore; vdesc =vchan_find_desc (&jzchan->vchan, cookie);if (vdesc) {
@@ -660,6 +660,7 @@ static enum dma_status jz4780_dma_tx_sta && jzchan->desc->status & (JZ_DMA_DCS_AR | JZ_DMA_DCS_HLT)) status =DMA_ERROR ; +out_unlock_irqrestore:spin_unlock_irqrestore (&jzchan->vchan.lock, flags);return status; }