diff options
-rw-r--r-- | 0000_README | 4 | ||||
-rw-r--r-- | 1006_linux-5.18.7.patch | 779 |
2 files changed, 783 insertions, 0 deletions
diff --git a/0000_README b/0000_README index 84b72755..17ef0755 100644 --- a/0000_README +++ b/0000_README @@ -67,6 +67,10 @@ Patch: 1005_linux-5.18.6.patch From: http://www.kernel.org Desc: Linux 5.18.6 +Patch: 1006_linux-5.18.7.patch +From: http://www.kernel.org +Desc: Linux 5.18.7 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1006_linux-5.18.7.patch b/1006_linux-5.18.7.patch new file mode 100644 index 00000000..ec6938d8 --- /dev/null +++ b/1006_linux-5.18.7.patch @@ -0,0 +1,779 @@ +diff --git a/Documentation/devicetree/bindings/nvmem/fsl,layerscape-sfp.yaml b/Documentation/devicetree/bindings/nvmem/fsl,layerscape-sfp.yaml +index 80914b93638e4..24c5e38584528 100644 +--- a/Documentation/devicetree/bindings/nvmem/fsl,layerscape-sfp.yaml ++++ b/Documentation/devicetree/bindings/nvmem/fsl,layerscape-sfp.yaml +@@ -24,15 +24,29 @@ properties: + reg: + maxItems: 1 + ++ clocks: ++ maxItems: 1 ++ description: ++ The SFP clock. Typically, this is the platform clock divided by 4. ++ ++ clock-names: ++ const: sfp ++ + required: + - compatible + - reg ++ - clock-names ++ - clocks + + unevaluatedProperties: false + + examples: + - | ++ #include <dt-bindings/clock/fsl,qoriq-clockgen.h> + efuse@1e80000 { + compatible = "fsl,ls1028a-sfp"; + reg = <0x1e80000 0x8000>; ++ clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL ++ QORIQ_CLK_PLL_DIV(4)>; ++ clock-names = "sfp"; + }; +diff --git a/Makefile b/Makefile +index 27850d452d652..61d63068553c8 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 5 + PATCHLEVEL = 18 +-SUBLEVEL = 6 ++SUBLEVEL = 7 + EXTRAVERSION = + NAME = Superb Owl + +diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c +index 697df02362af1..4909dcd762e8c 100644 +--- a/arch/s390/mm/pgtable.c ++++ b/arch/s390/mm/pgtable.c +@@ -748,7 +748,7 @@ void ptep_zap_key(struct mm_struct *mm, unsigned long addr, pte_t *ptep) + pgste_val(pgste) |= PGSTE_GR_BIT | PGSTE_GC_BIT; + ptev = pte_val(*ptep); + if (!(ptev & _PAGE_INVALID) && (ptev & _PAGE_WRITE)) +- page_set_storage_key(ptev & PAGE_MASK, PAGE_DEFAULT_KEY, 1); ++ page_set_storage_key(ptev & PAGE_MASK, PAGE_DEFAULT_KEY, 0); + pgste_set_unlock(ptep, pgste); + preempt_enable(); + } +diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h +index 34c9dbb6a47d6..686a9d75a0e41 100644 +--- a/arch/x86/boot/boot.h ++++ b/arch/x86/boot/boot.h +@@ -110,66 +110,78 @@ typedef unsigned int addr_t; + + static inline u8 rdfs8(addr_t addr) + { ++ u8 *ptr = (u8 *)absolute_pointer(addr); + u8 v; +- asm volatile("movb %%fs:%1,%0" : "=q" (v) : "m" (*(u8 *)addr)); ++ asm volatile("movb %%fs:%1,%0" : "=q" (v) : "m" (*ptr)); + return v; + } + static inline u16 rdfs16(addr_t addr) + { ++ u16 *ptr = (u16 *)absolute_pointer(addr); + u16 v; +- asm volatile("movw %%fs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr)); ++ asm volatile("movw %%fs:%1,%0" : "=r" (v) : "m" (*ptr)); + return v; + } + static inline u32 rdfs32(addr_t addr) + { ++ u32 *ptr = (u32 *)absolute_pointer(addr); + u32 v; +- asm volatile("movl %%fs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr)); ++ asm volatile("movl %%fs:%1,%0" : "=r" (v) : "m" (*ptr)); + return v; + } + + static inline void wrfs8(u8 v, addr_t addr) + { +- asm volatile("movb %1,%%fs:%0" : "+m" (*(u8 *)addr) : "qi" (v)); ++ u8 *ptr = (u8 *)absolute_pointer(addr); ++ asm volatile("movb %1,%%fs:%0" : "+m" (*ptr) : "qi" (v)); + } + static inline void wrfs16(u16 v, addr_t addr) + { +- asm volatile("movw %1,%%fs:%0" : "+m" (*(u16 *)addr) : "ri" (v)); ++ u16 *ptr = (u16 *)absolute_pointer(addr); ++ asm volatile("movw %1,%%fs:%0" : "+m" (*ptr) : "ri" (v)); + } + static inline void wrfs32(u32 v, addr_t addr) + { +- asm volatile("movl %1,%%fs:%0" : "+m" (*(u32 *)addr) : "ri" (v)); ++ u32 *ptr = (u32 *)absolute_pointer(addr); ++ asm volatile("movl %1,%%fs:%0" : "+m" (*ptr) : "ri" (v)); + } + + static inline u8 rdgs8(addr_t addr) + { ++ u8 *ptr = (u8 *)absolute_pointer(addr); + u8 v; +- asm volatile("movb %%gs:%1,%0" : "=q" (v) : "m" (*(u8 *)addr)); ++ asm volatile("movb %%gs:%1,%0" : "=q" (v) : "m" (*ptr)); + return v; + } + static inline u16 rdgs16(addr_t addr) + { ++ u16 *ptr = (u16 *)absolute_pointer(addr); + u16 v; +- asm volatile("movw %%gs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr)); ++ asm volatile("movw %%gs:%1,%0" : "=r" (v) : "m" (*ptr)); + return v; + } + static inline u32 rdgs32(addr_t addr) + { ++ u32 *ptr = (u32 *)absolute_pointer(addr); + u32 v; +- asm volatile("movl %%gs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr)); ++ asm volatile("movl %%gs:%1,%0" : "=r" (v) : "m" (*ptr)); + return v; + } + + static inline void wrgs8(u8 v, addr_t addr) + { +- asm volatile("movb %1,%%gs:%0" : "+m" (*(u8 *)addr) : "qi" (v)); ++ u8 *ptr = (u8 *)absolute_pointer(addr); ++ asm volatile("movb %1,%%gs:%0" : "+m" (*ptr) : "qi" (v)); + } + static inline void wrgs16(u16 v, addr_t addr) + { +- asm volatile("movw %1,%%gs:%0" : "+m" (*(u16 *)addr) : "ri" (v)); ++ u16 *ptr = (u16 *)absolute_pointer(addr); ++ asm volatile("movw %1,%%gs:%0" : "+m" (*ptr) : "ri" (v)); + } + static inline void wrgs32(u32 v, addr_t addr) + { +- asm volatile("movl %1,%%gs:%0" : "+m" (*(u32 *)addr) : "ri" (v)); ++ u32 *ptr = (u32 *)absolute_pointer(addr); ++ asm volatile("movl %1,%%gs:%0" : "+m" (*ptr) : "ri" (v)); + } + + /* Note: these only return true/false, not a signed return value! */ +diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c +index e3add857c2c9d..c421af5a3cdce 100644 +--- a/arch/x86/boot/main.c ++++ b/arch/x86/boot/main.c +@@ -33,7 +33,7 @@ static void copy_boot_params(void) + u16 cl_offset; + }; + const struct old_cmdline * const oldcmd = +- (const struct old_cmdline *)OLD_CL_ADDRESS; ++ absolute_pointer(OLD_CL_ADDRESS); + + BUILD_BUG_ON(sizeof(boot_params) != 4096); + memcpy(&boot_params.hdr, &hdr, sizeof(hdr)); +diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c +index b04a6a7bf5669..435dc00d04e5d 100644 +--- a/drivers/net/ethernet/sun/cassini.c ++++ b/drivers/net/ethernet/sun/cassini.c +@@ -1313,7 +1313,7 @@ static void cas_init_rx_dma(struct cas *cp) + writel(val, cp->regs + REG_RX_PAGE_SIZE); + + /* enable the header parser if desired */ +- if (CAS_HP_FIRMWARE == cas_prog_null) ++ if (&CAS_HP_FIRMWARE[0] == &cas_prog_null[0]) + return; + + val = CAS_BASE(HP_CFG_NUM_CPU, CAS_NCPUS > 63 ? 0 : CAS_NCPUS); +@@ -3780,7 +3780,7 @@ static void cas_reset(struct cas *cp, int blkflag) + + /* program header parser */ + if ((cp->cas_flags & CAS_FLAG_TARGET_ABORT) || +- (CAS_HP_ALT_FIRMWARE == cas_prog_null)) { ++ (&CAS_HP_ALT_FIRMWARE[0] == &cas_prog_null[0])) { + cas_load_firmware(cp, CAS_HP_FIRMWARE); + } else { + cas_load_firmware(cp, CAS_HP_ALT_FIRMWARE); +diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c +index 51fe51bb05041..15e6a6aded319 100644 +--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c ++++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c +@@ -2386,10 +2386,7 @@ void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel) + rtl_dbg(rtlpriv, COMP_SCAN, DBG_LOUD, + "Just Read IQK Matrix reg for channel:%d....\n", + channel); +- if ((rtlphy->iqk_matrix[indexforchannel]. +- value[0] != NULL) +- /*&&(regea4 != 0) */) +- _rtl92d_phy_patha_fill_iqk_matrix(hw, true, ++ _rtl92d_phy_patha_fill_iqk_matrix(hw, true, + rtlphy->iqk_matrix[ + indexforchannel].value, 0, + (rtlphy->iqk_matrix[ +diff --git a/drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c b/drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c +index c6b032f95d2e4..4627847c6daab 100644 +--- a/drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c ++++ b/drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c +@@ -372,8 +372,6 @@ bool ipc_protocol_dl_td_prepare(struct iosm_protocol *ipc_protocol, + struct sk_buff *ipc_protocol_dl_td_process(struct iosm_protocol *ipc_protocol, + struct ipc_pipe *pipe) + { +- u32 tail = +- le32_to_cpu(ipc_protocol->p_ap_shm->tail_array[pipe->pipe_nr]); + struct ipc_protocol_td *p_td; + struct sk_buff *skb; + +@@ -403,14 +401,6 @@ struct sk_buff *ipc_protocol_dl_td_process(struct iosm_protocol *ipc_protocol, + goto ret; + } + +- if (!IPC_CB(skb)) { +- dev_err(ipc_protocol->dev, "pipe# %d, tail: %d skb_cb is NULL", +- pipe->pipe_nr, tail); +- ipc_pcie_kfree_skb(ipc_protocol->pcie, skb); +- skb = NULL; +- goto ret; +- } +- + if (p_td->buffer.address != IPC_CB(skb)->mapping) { + dev_err(ipc_protocol->dev, "invalid buf=%llx or skb=%p", + (unsigned long long)p_td->buffer.address, skb->data); +diff --git a/fs/io_uring.c b/fs/io_uring.c +index 3d123ca028c97..68aab48838e41 100644 +--- a/fs/io_uring.c ++++ b/fs/io_uring.c +@@ -1647,7 +1647,7 @@ static inline void io_req_track_inflight(struct io_kiocb *req) + { + if (!(req->flags & REQ_F_INFLIGHT)) { + req->flags |= REQ_F_INFLIGHT; +- atomic_inc(¤t->io_uring->inflight_tracked); ++ atomic_inc(&req->task->io_uring->inflight_tracked); + } + } + +diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c +index 985e995d2a398..4f897e1095470 100644 +--- a/fs/notify/fanotify/fanotify.c ++++ b/fs/notify/fanotify/fanotify.c +@@ -319,12 +319,8 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group, + return 0; + } + +- fsnotify_foreach_iter_type(type) { +- if (!fsnotify_iter_should_report_type(iter_info, type)) +- continue; +- mark = iter_info->marks[type]; +- +- /* Apply ignore mask regardless of ISDIR and ON_CHILD flags */ ++ fsnotify_foreach_iter_mark_type(iter_info, mark, type) { ++ /* Apply ignore mask regardless of mark's ISDIR flag */ + marks_ignored_mask |= mark->ignored_mask; + + /* +@@ -334,14 +330,6 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group, + if (event_mask & FS_ISDIR && !(mark->mask & FS_ISDIR)) + continue; + +- /* +- * If the event is on a child and this mark is on a parent not +- * watching children, don't send it! +- */ +- if (type == FSNOTIFY_ITER_TYPE_PARENT && +- !(mark->mask & FS_EVENT_ON_CHILD)) +- continue; +- + marks_mask |= mark->mask; + + /* Record the mark types of this group that matched the event */ +@@ -849,16 +837,14 @@ out: + */ + static __kernel_fsid_t fanotify_get_fsid(struct fsnotify_iter_info *iter_info) + { ++ struct fsnotify_mark *mark; + int type; + __kernel_fsid_t fsid = {}; + +- fsnotify_foreach_iter_type(type) { ++ fsnotify_foreach_iter_mark_type(iter_info, mark, type) { + struct fsnotify_mark_connector *conn; + +- if (!fsnotify_iter_should_report_type(iter_info, type)) +- continue; +- +- conn = READ_ONCE(iter_info->marks[type]->connector); ++ conn = READ_ONCE(mark->connector); + /* Mark is just getting destroyed or created? */ + if (!conn) + continue; +diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c +index 70a8516b78bc5..6d63423cd4928 100644 +--- a/fs/notify/fsnotify.c ++++ b/fs/notify/fsnotify.c +@@ -290,22 +290,15 @@ static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask, + } + + if (parent_mark) { +- /* +- * parent_mark indicates that the parent inode is watching +- * children and interested in this event, which is an event +- * possible on child. But is *this mark* watching children and +- * interested in this event? +- */ +- if (parent_mark->mask & FS_EVENT_ON_CHILD) { +- ret = fsnotify_handle_inode_event(group, parent_mark, mask, +- data, data_type, dir, name, 0); +- if (ret) +- return ret; +- } +- if (!inode_mark) +- return 0; ++ ret = fsnotify_handle_inode_event(group, parent_mark, mask, ++ data, data_type, dir, name, 0); ++ if (ret) ++ return ret; + } + ++ if (!inode_mark) ++ return 0; ++ + if (mask & FS_EVENT_ON_CHILD) { + /* + * Some events can be sent on both parent dir and child marks +@@ -335,31 +328,23 @@ static int send_to_group(__u32 mask, const void *data, int data_type, + struct fsnotify_mark *mark; + int type; + +- if (WARN_ON(!iter_info->report_mask)) ++ if (!iter_info->report_mask) + return 0; + + /* clear ignored on inode modification */ + if (mask & FS_MODIFY) { +- fsnotify_foreach_iter_type(type) { +- if (!fsnotify_iter_should_report_type(iter_info, type)) +- continue; +- mark = iter_info->marks[type]; +- if (mark && +- !(mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)) ++ fsnotify_foreach_iter_mark_type(iter_info, mark, type) { ++ if (!(mark->flags & ++ FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)) + mark->ignored_mask = 0; + } + } + +- fsnotify_foreach_iter_type(type) { +- if (!fsnotify_iter_should_report_type(iter_info, type)) +- continue; +- mark = iter_info->marks[type]; +- /* does the object mark tell us to do something? */ +- if (mark) { +- group = mark->group; +- marks_mask |= mark->mask; +- marks_ignored_mask |= mark->ignored_mask; +- } ++ /* Are any of the group marks interested in this event? */ ++ fsnotify_foreach_iter_mark_type(iter_info, mark, type) { ++ group = mark->group; ++ marks_mask |= mark->mask; ++ marks_ignored_mask |= mark->ignored_mask; + } + + pr_debug("%s: group=%p mask=%x marks_mask=%x marks_ignored_mask=%x data=%p data_type=%d dir=%p cookie=%d\n", +@@ -403,11 +388,11 @@ static struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark) + + /* + * iter_info is a multi head priority queue of marks. +- * Pick a subset of marks from queue heads, all with the +- * same group and set the report_mask for selected subset. +- * Returns the report_mask of the selected subset. ++ * Pick a subset of marks from queue heads, all with the same group ++ * and set the report_mask to a subset of the selected marks. ++ * Returns false if there are no more groups to iterate. + */ +-static unsigned int fsnotify_iter_select_report_types( ++static bool fsnotify_iter_select_report_types( + struct fsnotify_iter_info *iter_info) + { + struct fsnotify_group *max_prio_group = NULL; +@@ -423,30 +408,48 @@ static unsigned int fsnotify_iter_select_report_types( + } + + if (!max_prio_group) +- return 0; ++ return false; + + /* Set the report mask for marks from same group as max prio group */ ++ iter_info->current_group = max_prio_group; + iter_info->report_mask = 0; + fsnotify_foreach_iter_type(type) { + mark = iter_info->marks[type]; +- if (mark && +- fsnotify_compare_groups(max_prio_group, mark->group) == 0) ++ if (mark && mark->group == iter_info->current_group) { ++ /* ++ * FSNOTIFY_ITER_TYPE_PARENT indicates that this inode ++ * is watching children and interested in this event, ++ * which is an event possible on child. ++ * But is *this mark* watching children? ++ */ ++ if (type == FSNOTIFY_ITER_TYPE_PARENT && ++ !(mark->mask & FS_EVENT_ON_CHILD)) ++ continue; ++ + fsnotify_iter_set_report_type(iter_info, type); ++ } + } + +- return iter_info->report_mask; ++ return true; + } + + /* +- * Pop from iter_info multi head queue, the marks that were iterated in the ++ * Pop from iter_info multi head queue, the marks that belong to the group of + * current iteration step. + */ + static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info) + { ++ struct fsnotify_mark *mark; + int type; + ++ /* ++ * We cannot use fsnotify_foreach_iter_mark_type() here because we ++ * may need to advance a mark of type X that belongs to current_group ++ * but was not selected for reporting. ++ */ + fsnotify_foreach_iter_type(type) { +- if (fsnotify_iter_should_report_type(iter_info, type)) ++ mark = iter_info->marks[type]; ++ if (mark && mark->group == iter_info->current_group) + iter_info->marks[type] = + fsnotify_next_mark(iter_info->marks[type]); + } +diff --git a/fs/zonefs/super.c b/fs/zonefs/super.c +index 1c2ece9611287..15a4c7c07a3bf 100644 +--- a/fs/zonefs/super.c ++++ b/fs/zonefs/super.c +@@ -72,15 +72,51 @@ static inline void zonefs_i_size_write(struct inode *inode, loff_t isize) + zi->i_flags &= ~ZONEFS_ZONE_OPEN; + } + +-static int zonefs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, +- unsigned int flags, struct iomap *iomap, +- struct iomap *srcmap) ++static int zonefs_read_iomap_begin(struct inode *inode, loff_t offset, ++ loff_t length, unsigned int flags, ++ struct iomap *iomap, struct iomap *srcmap) + { + struct zonefs_inode_info *zi = ZONEFS_I(inode); + struct super_block *sb = inode->i_sb; + loff_t isize; + +- /* All I/Os should always be within the file maximum size */ ++ /* ++ * All blocks are always mapped below EOF. If reading past EOF, ++ * act as if there is a hole up to the file maximum size. ++ */ ++ mutex_lock(&zi->i_truncate_mutex); ++ iomap->bdev = inode->i_sb->s_bdev; ++ iomap->offset = ALIGN_DOWN(offset, sb->s_blocksize); ++ isize = i_size_read(inode); ++ if (iomap->offset >= isize) { ++ iomap->type = IOMAP_HOLE; ++ iomap->addr = IOMAP_NULL_ADDR; ++ iomap->length = length; ++ } else { ++ iomap->type = IOMAP_MAPPED; ++ iomap->addr = (zi->i_zsector << SECTOR_SHIFT) + iomap->offset; ++ iomap->length = isize - iomap->offset; ++ } ++ mutex_unlock(&zi->i_truncate_mutex); ++ ++ trace_zonefs_iomap_begin(inode, iomap); ++ ++ return 0; ++} ++ ++static const struct iomap_ops zonefs_read_iomap_ops = { ++ .iomap_begin = zonefs_read_iomap_begin, ++}; ++ ++static int zonefs_write_iomap_begin(struct inode *inode, loff_t offset, ++ loff_t length, unsigned int flags, ++ struct iomap *iomap, struct iomap *srcmap) ++{ ++ struct zonefs_inode_info *zi = ZONEFS_I(inode); ++ struct super_block *sb = inode->i_sb; ++ loff_t isize; ++ ++ /* All write I/Os should always be within the file maximum size */ + if (WARN_ON_ONCE(offset + length > zi->i_max_size)) + return -EIO; + +@@ -90,7 +126,7 @@ static int zonefs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, + * operation. + */ + if (WARN_ON_ONCE(zi->i_ztype == ZONEFS_ZTYPE_SEQ && +- (flags & IOMAP_WRITE) && !(flags & IOMAP_DIRECT))) ++ !(flags & IOMAP_DIRECT))) + return -EIO; + + /* +@@ -99,47 +135,44 @@ static int zonefs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, + * write pointer) and unwriten beyond. + */ + mutex_lock(&zi->i_truncate_mutex); ++ iomap->bdev = inode->i_sb->s_bdev; ++ iomap->offset = ALIGN_DOWN(offset, sb->s_blocksize); ++ iomap->addr = (zi->i_zsector << SECTOR_SHIFT) + iomap->offset; + isize = i_size_read(inode); +- if (offset >= isize) ++ if (iomap->offset >= isize) { + iomap->type = IOMAP_UNWRITTEN; +- else ++ iomap->length = zi->i_max_size - iomap->offset; ++ } else { + iomap->type = IOMAP_MAPPED; +- if (flags & IOMAP_WRITE) +- length = zi->i_max_size - offset; +- else +- length = min(length, isize - offset); ++ iomap->length = isize - iomap->offset; ++ } + mutex_unlock(&zi->i_truncate_mutex); + +- iomap->offset = ALIGN_DOWN(offset, sb->s_blocksize); +- iomap->length = ALIGN(offset + length, sb->s_blocksize) - iomap->offset; +- iomap->bdev = inode->i_sb->s_bdev; +- iomap->addr = (zi->i_zsector << SECTOR_SHIFT) + iomap->offset; +- + trace_zonefs_iomap_begin(inode, iomap); + + return 0; + } + +-static const struct iomap_ops zonefs_iomap_ops = { +- .iomap_begin = zonefs_iomap_begin, ++static const struct iomap_ops zonefs_write_iomap_ops = { ++ .iomap_begin = zonefs_write_iomap_begin, + }; + + static int zonefs_readpage(struct file *unused, struct page *page) + { +- return iomap_readpage(page, &zonefs_iomap_ops); ++ return iomap_readpage(page, &zonefs_read_iomap_ops); + } + + static void zonefs_readahead(struct readahead_control *rac) + { +- iomap_readahead(rac, &zonefs_iomap_ops); ++ iomap_readahead(rac, &zonefs_read_iomap_ops); + } + + /* + * Map blocks for page writeback. This is used only on conventional zone files, + * which implies that the page range can only be within the fixed inode size. + */ +-static int zonefs_map_blocks(struct iomap_writepage_ctx *wpc, +- struct inode *inode, loff_t offset) ++static int zonefs_write_map_blocks(struct iomap_writepage_ctx *wpc, ++ struct inode *inode, loff_t offset) + { + struct zonefs_inode_info *zi = ZONEFS_I(inode); + +@@ -153,12 +186,12 @@ static int zonefs_map_blocks(struct iomap_writepage_ctx *wpc, + offset < wpc->iomap.offset + wpc->iomap.length) + return 0; + +- return zonefs_iomap_begin(inode, offset, zi->i_max_size - offset, +- IOMAP_WRITE, &wpc->iomap, NULL); ++ return zonefs_write_iomap_begin(inode, offset, zi->i_max_size - offset, ++ IOMAP_WRITE, &wpc->iomap, NULL); + } + + static const struct iomap_writeback_ops zonefs_writeback_ops = { +- .map_blocks = zonefs_map_blocks, ++ .map_blocks = zonefs_write_map_blocks, + }; + + static int zonefs_writepage(struct page *page, struct writeback_control *wbc) +@@ -188,7 +221,8 @@ static int zonefs_swap_activate(struct swap_info_struct *sis, + return -EINVAL; + } + +- return iomap_swapfile_activate(sis, swap_file, span, &zonefs_iomap_ops); ++ return iomap_swapfile_activate(sis, swap_file, span, ++ &zonefs_read_iomap_ops); + } + + static const struct address_space_operations zonefs_file_aops = { +@@ -607,7 +641,7 @@ static vm_fault_t zonefs_filemap_page_mkwrite(struct vm_fault *vmf) + + /* Serialize against truncates */ + filemap_invalidate_lock_shared(inode->i_mapping); +- ret = iomap_page_mkwrite(vmf, &zonefs_iomap_ops); ++ ret = iomap_page_mkwrite(vmf, &zonefs_write_iomap_ops); + filemap_invalidate_unlock_shared(inode->i_mapping); + + sb_end_pagefault(inode->i_sb); +@@ -860,7 +894,7 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from) + if (append) + ret = zonefs_file_dio_append(iocb, from); + else +- ret = iomap_dio_rw(iocb, from, &zonefs_iomap_ops, ++ ret = iomap_dio_rw(iocb, from, &zonefs_write_iomap_ops, + &zonefs_write_dio_ops, 0, 0); + if (zi->i_ztype == ZONEFS_ZTYPE_SEQ && + (ret > 0 || ret == -EIOCBQUEUED)) { +@@ -902,7 +936,7 @@ static ssize_t zonefs_file_buffered_write(struct kiocb *iocb, + if (ret <= 0) + goto inode_unlock; + +- ret = iomap_file_buffered_write(iocb, from, &zonefs_iomap_ops); ++ ret = iomap_file_buffered_write(iocb, from, &zonefs_write_iomap_ops); + if (ret > 0) + iocb->ki_pos += ret; + else if (ret == -EIO) +@@ -995,7 +1029,7 @@ static ssize_t zonefs_file_read_iter(struct kiocb *iocb, struct iov_iter *to) + goto inode_unlock; + } + file_accessed(iocb->ki_filp); +- ret = iomap_dio_rw(iocb, to, &zonefs_iomap_ops, ++ ret = iomap_dio_rw(iocb, to, &zonefs_read_iomap_ops, + &zonefs_read_dio_ops, 0, 0); + } else { + ret = generic_file_read_iter(iocb, to); +diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h +index 0805b74cae441..beb9c99fea07d 100644 +--- a/include/linux/fsnotify_backend.h ++++ b/include/linux/fsnotify_backend.h +@@ -370,6 +370,7 @@ static inline bool fsnotify_valid_obj_type(unsigned int obj_type) + + struct fsnotify_iter_info { + struct fsnotify_mark *marks[FSNOTIFY_ITER_TYPE_COUNT]; ++ struct fsnotify_group *current_group; + unsigned int report_mask; + int srcu_idx; + }; +@@ -386,20 +387,31 @@ static inline void fsnotify_iter_set_report_type( + iter_info->report_mask |= (1U << iter_type); + } + +-static inline void fsnotify_iter_set_report_type_mark( +- struct fsnotify_iter_info *iter_info, int iter_type, +- struct fsnotify_mark *mark) ++static inline struct fsnotify_mark *fsnotify_iter_mark( ++ struct fsnotify_iter_info *iter_info, int iter_type) + { +- iter_info->marks[iter_type] = mark; +- iter_info->report_mask |= (1U << iter_type); ++ if (fsnotify_iter_should_report_type(iter_info, iter_type)) ++ return iter_info->marks[iter_type]; ++ return NULL; ++} ++ ++static inline int fsnotify_iter_step(struct fsnotify_iter_info *iter, int type, ++ struct fsnotify_mark **markp) ++{ ++ while (type < FSNOTIFY_ITER_TYPE_COUNT) { ++ *markp = fsnotify_iter_mark(iter, type); ++ if (*markp) ++ break; ++ type++; ++ } ++ return type; + } + + #define FSNOTIFY_ITER_FUNCS(name, NAME) \ + static inline struct fsnotify_mark *fsnotify_iter_##name##_mark( \ + struct fsnotify_iter_info *iter_info) \ + { \ +- return (iter_info->report_mask & (1U << FSNOTIFY_ITER_TYPE_##NAME)) ? \ +- iter_info->marks[FSNOTIFY_ITER_TYPE_##NAME] : NULL; \ ++ return fsnotify_iter_mark(iter_info, FSNOTIFY_ITER_TYPE_##NAME); \ + } + + FSNOTIFY_ITER_FUNCS(inode, INODE) +@@ -409,6 +421,11 @@ FSNOTIFY_ITER_FUNCS(sb, SB) + + #define fsnotify_foreach_iter_type(type) \ + for (type = 0; type < FSNOTIFY_ITER_TYPE_COUNT; type++) ++#define fsnotify_foreach_iter_mark_type(iter, mark, type) \ ++ for (type = 0; \ ++ type = fsnotify_iter_step(iter, type, &mark), \ ++ type < FSNOTIFY_ITER_TYPE_COUNT; \ ++ type++) + + /* + * fsnotify_connp_t is what we embed in objects which connector can be attached +diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c +index 0918a39279f6c..feef799884d1f 100644 +--- a/kernel/bpf/btf.c ++++ b/kernel/bpf/btf.c +@@ -5769,6 +5769,7 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, + struct bpf_reg_state *regs, + bool ptr_to_mem_ok) + { ++ enum bpf_prog_type prog_type = resolve_prog_type(env->prog); + struct bpf_verifier_log *log = &env->log; + u32 i, nargs, ref_id, ref_obj_id = 0; + bool is_kfunc = btf_is_kernel(btf); +@@ -5834,8 +5835,7 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, + if (ret < 0) + return ret; + +- if (btf_get_prog_ctx_type(log, btf, t, +- env->prog->type, i)) { ++ if (btf_get_prog_ctx_type(log, btf, t, prog_type, i)) { + /* If function expects ctx type in BTF check that caller + * is passing PTR_TO_CTX. + */ +diff --git a/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c b/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c +index d9aad15e0d242..02bb8cbf91949 100644 +--- a/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c ++++ b/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c +@@ -395,6 +395,18 @@ static void test_func_map_prog_compatibility(void) + "./test_attach_probe.o"); + } + ++static void test_func_replace_global_func(void) ++{ ++ const char *prog_name[] = { ++ "freplace/test_pkt_access", ++ }; ++ ++ test_fexit_bpf2bpf_common("./freplace_global_func.o", ++ "./test_pkt_access.o", ++ ARRAY_SIZE(prog_name), ++ prog_name, false, NULL); ++} ++ + /* NOTE: affect other tests, must run in serial mode */ + void serial_test_fexit_bpf2bpf(void) + { +@@ -416,4 +428,6 @@ void serial_test_fexit_bpf2bpf(void) + test_func_replace_multi(); + if (test__start_subtest("fmod_ret_freplace")) + test_fmod_ret_freplace(); ++ if (test__start_subtest("func_replace_global_func")) ++ test_func_replace_global_func(); + } +diff --git a/tools/testing/selftests/bpf/progs/freplace_global_func.c b/tools/testing/selftests/bpf/progs/freplace_global_func.c +new file mode 100644 +index 0000000000000..96cb61a6ce87a +--- /dev/null ++++ b/tools/testing/selftests/bpf/progs/freplace_global_func.c +@@ -0,0 +1,18 @@ ++// SPDX-License-Identifier: GPL-2.0 ++#include <linux/bpf.h> ++#include <bpf/bpf_helpers.h> ++ ++__noinline ++int test_ctx_global_func(struct __sk_buff *skb) ++{ ++ volatile int retval = 1; ++ return retval; ++} ++ ++SEC("freplace/test_pkt_access") ++int new_test_pkt_access(struct __sk_buff *skb) ++{ ++ return test_ctx_global_func(skb); ++} ++ ++char _license[] SEC("license") = "GPL"; |