Linux 6.6.47
Greg Kroah-Hartman
maintainerI'm announcing the release of the 6.6.47 kernel.
All users of the 6.6 kernel series must upgrade.
The updated 6.6.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-6.6.y
and can be browsed at the normal kernel.org git web browser:
https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary
thanks,
greg k-h
------------
Documentation/bpf/map_lpm_trie.rst | 2 Documentation/mm/page_table_check.rst | 9 Makefile | 2 arch/arm64/kvm/hyp/pgtable.c | 12 - arch/loongarch/include/uapi/asm/unistd.h | 1 arch/x86/include/asm/pgtable.h | 18 - drivers/ata/libata-scsi.c | 15 + drivers/isdn/mISDN/socket.c | 10 drivers/media/usb/dvb-usb/dvb-usb-init.c | 35 --- drivers/net/ppp/pppoe.c | 23 -- drivers/nvme/host/pci.c | 7 fs/binfmt_flat.c | 4 fs/buffer.c | 2 fs/cramfs/inode.c | 2 fs/erofs/decompressor.c | 8 fs/exec.c | 8 fs/ext4/inode.c | 24 +- fs/ext4/xattr.c | 155 ++++++-------- fs/f2fs/extent_cache.c | 48 +--- fs/f2fs/f2fs.h | 2 fs/f2fs/gc.c | 10 fs/f2fs/inode.c | 10 fs/fhandle.c | 6 fs/jfs/jfs_dmap.c | 2 fs/jfs/jfs_dtree.c | 2 fs/jfs/jfs_logmgr.c | 33 +-- fs/jfs/jfs_logmgr.h | 2 fs/jfs/jfs_mount.c | 3 fs/lockd/svc.c | 3 fs/nfs/callback.c | 3 fs/nfsd/cache.h | 2 fs/nfsd/export.c | 32 ++ fs/nfsd/export.h | 4 fs/nfsd/netns.h | 25 +- fs/nfsd/nfs4proc.c | 6 fs/nfsd/nfs4state.c | 3 fs/nfsd/nfscache.c | 40 --- fs/nfsd/nfsctl.c | 16 - fs/nfsd/nfsd.h | 1 fs/nfsd/nfsfh.c | 3 fs/nfsd/nfssvc.c | 14 - fs/nfsd/stats.c | 54 ++-- fs/nfsd/stats.h | 90 +++----- fs/nfsd/vfs.c | 6 fs/ntfs3/frecord.c | 75 ++++++ fs/quota/quota_tree.c | 128 ++++++++--- fs/quota/quota_v2.c | 15 - fs/reiserfs/stree.c | 2 fs/romfs/super.c | 2 fs/squashfs/block.c | 2 fs/squashfs/file.c | 3 fs/squashfs/file_direct.c | 6 fs/super.c | 15 - include/linux/cgroup-defs.h | 7 include/linux/fs.h | 3 include/linux/sockptr.h | 25 ++ include/linux/sunrpc/svc.h | 5 include/uapi/linux/bpf.h | 19 + kernel/bpf/lpm_trie.c | 33 +-- kernel/cgroup/cgroup-internal.h | 3 kernel/cgroup/cgroup.c | 23 +- kernel/irq/cpuhotplug.c | 27 ++ kernel/irq/manage.c | 12 - mm/debug_vm_pgtable.c | 31 -- mm/gup.c | 251 +++++++++++------------ mm/huge_memory.c | 6 mm/hugetlb.c | 2 mm/internal.h | 4 mm/page_table_check.c | 30 ++ net/bluetooth/rfcomm/sock.c | 14 - net/core/filter.c | 8 net/ipv4/fou_core.c | 2 net/ipv4/tcp_metrics.c | 7 net/mac80211/iface.c | 27 ++ net/nfc/llcp_sock.c | 12 - net/rds/recv.c | 13 + net/sched/sch_generic.c | 5 net/sctp/inqueue.c | 14 - net/sunrpc/stats.c | 2 net/sunrpc/svc.c | 39 ++- net/wireless/nl80211.c | 6 samples/bpf/map_perf_test_user.c | 2 samples/bpf/xdp_router_ipv4_user.c | 2 sound/soc/soc-topology.c | 32 -- sound/usb/mixer.c | 7 tools/include/uapi/linux/bpf.h | 19 + tools/testing/selftests/bpf/progs/map_ptr_kern.c | 2 tools/testing/selftests/bpf/test_lpm_map.c | 18 - tools/testing/selftests/net/tls.c | 14 + 89 files changed, 1003 insertions(+), 728 deletions(-)
Alexei Starovoitov (1):
bpf: Avoid kfree_rcu() under lock in bpf_lpm_trie.
Allison Henderson (1):
net:rds: Fix possible deadlock in rds_message_put
Amadeusz Sławiński (2):
ASoC: topology: Clean up route loading
ASoC: topology: Fix route memory corruption
Chao Yu (2):
f2fs: fix to do sanity check on F2FS_INLINE_DATA flag in inode during GC
f2fs: fix to cover read extent cache access with lock
Chuck Lever (2):
NFSD: Rewrite synopsis of nfsd_percpu_counters_init()
NFSD: Fix frame size warning in svc_export_parse()
Dave Kleikamp (1):
Revert "jfs: fix shift-out-of-bounds in dbJoin"
David Stevens (1):
genirq/cpuhotplug: Skip suspended interrupts when restoring affinity
Dmitry Antipov (1):
net: sctp: fix skb leak in sctp_inq_free()
Dongli Zhang (1):
genirq/cpuhotplug: Retry with cpu_online_mask when migration fails
Edward Adam Davis (2):
reiserfs: fix uninit-value in comp_keys
jfs: fix null ptr deref in dtInsertEntry
Eric Dumazet (5):
tcp_metrics: optimize tcp_metrics_flush_all()
mISDN: fix MISDN_TIME_STAMP handling
net: add copy_safe_from_sockptr() helper
nfc: llcp: fix nfc_llcp_setsockopt() unsafe copies
wifi: cfg80211: restrict NL80211_ATTR_TXQ_QUANTUM values
Gao Xiang (1):
erofs: avoid debugging output for (de)compressed data
Gavrilov Ilia (1):
pppoe: Fix memory leak in pppoe_sendmsg()
Greg Kroah-Hartman (1):
Linux 6.6.47
Gustavo A. R. Silva (1):
fs: Annotate struct file_handle with __counted_by() and use struct_size()
Huacai Chen (1):
LoongArch: Define __ARCH_WANT_NEW_STAT in unistd.h
Jakub Kicinski (1):
net: don't dump stack on queue timeout
Jan Kara (5):
fs: Convert to bdev_open_by_dev()
jfs: Convert to bdev_open_by_dev()
quota: Detect loops in quota tree
ext4: fold quota accounting into ext4_xattr_inode_lookup_create()
ext4: do not create EA inode under buffer lock
Javier Carrasco (2):
Input: bcm5974 - check endpoint type before starting traffic Revert "Input: bcm5974 - check endpoint type before starting traffic"
Johannes Berg (2):
wifi: mac80211: take wiphy lock for MAC addr change
wifi: mac80211: fix change_address deadlock during unregister
John Fastabend (1):
net: tls, add test to capture error on large splice
Josef Bacik (10):
sunrpc: don't change ->sv_stats if it doesn't exist
nfsd: stop setting ->pg_stats for unused stats
sunrpc: pass in the sv_stats struct through svc_create_pooled
sunrpc: remove ->pg_stats from svc_program
sunrpc: use the struct net as the svc proc private
nfsd: rename NFSD_NET_* to NFSD_STATS_*
nfsd: expose /proc/net/sunrpc/nfsd in net namespaces
nfsd: make all of the nfsd stats per-network namespace
nfsd: remove nfsd_stats, make th_cnt a global counter
nfsd: make svc_stat per-network namespace instead of global
Kees Cook (3):
exec: Fix ToCToU between perm check and set-uid/gid usage
bpf: Replace bpf_lpm_trie_key 0-length array with flexible array
binfmt_flat: Fix corruption when not offsetting data start
Konstantin Komarov (1):
fs/ntfs3: Do copy_to_user out of run_lock
Lizhi Xu (2):
jfs: fix log->bdev_handle null ptr deref in lbmStartIO
squashfs: squashfs_read_data need to check if the length is 0
Luiz Augusto von Dentz (1):
Bluetooth: RFCOMM: Fix not validating setsockopt user input
Manas Ghandat (1):
jfs: fix shift-out-of-bounds in dbJoin
Matthew Wilcox (Oracle) (1):
ext4: convert ext4_da_do_write_end() to take a folio
Niklas Cassel (1):
Revert "ata: libata-scsi: Honor the D_SENSE bit for CK_COND=1 and no error"
Pei Li (1):
jfs: Fix shift-out-of-bounds in dbDiscardAG
Peter Xu (2):
mm/page_table_check: support userfault wr-protect entries mm/debug_vm_pgtable: drop RANDOM_ORVALUE trick
Phillip Lougher (1):
Squashfs: fix variable overflow triggered by sysbot
Sean Young (1):
media: Revert "media: dvb-usb: Fix unexpected infinite loop in dvb_usb_read_remote_control()"
Takashi Iwai (1):
ALSA: usb: Fix UBSAN warning in parse_audio_unit()
Waiman Long (1):
cgroup: Move rcu_head up near the top of cgroup_root
WangYuli (1):
nvme/pci: Add APST quirk for Lenovo N60z laptop
Will Deacon (2):
KVM: arm64: Don't defer TLB invalidation when zapping table entries
KVM: arm64: Don't pass a TLBI level hint when zapping table entries
Willem de Bruijn (1):
fou: remove warn in gue_gro_receive on unsupported protocol
Wojciech Gładysz (1):
ext4: sanity check for NULL pointer after ext4_force_shutdown
Yafang Shao (1):
cgroup: Make operations on the cgroup root_list RCU safe
Yang Shi (1):
mm: gup: stop abusing try_grab_folio
yunshui (1):
bpf, net: Use DEV_STAT_INC()
Greg Kroah-Hartman
maintainerDocumentation/bpf/map_lpm_trie.rst +1 -1
@@ -17,7 +17,7 @@ significant byte. LPM tries may be created with a maximum prefix length that is a multiple of 8, in the range from 8 to 2048. The key used for lookup and update -operations is a ``struct bpf_lpm_trie_key``, extended by +operations is a ``struct bpf_lpm_trie_key_u8``, extended by ``max_prefixlen/8`` bytes. - For IPv4 addresses the data length is 4 bytes
Documentation/mm/page_table_check.rst +8 -1
@@ -14,7 +14,7 @@ Page table check performs extra verifications at the time when new pages become accessible from the userspace by getting their page table entries (PTEs PMDs etc.) added into the table. -In case of detected corruption, the kernel is crashed. There is a small +In case of most detected corruption, the kernel is crashed. There is a small performance and memory overhead associated with the page table check. Therefore, it is disabled by default, but can be optionally enabled on systems where the extra hardening outweighs the performance costs. Also, because page table check
@@ -22,6 +22,13 @@ is synchronous, it can help with debugging double map memory corruption issues, by crashing kernel at the time wrong mapping occurs instead of later which is often the case with memory corruptions bugs. +It can also be used to do page table entry checks over various flags, dump +warnings when illegal combinations of entry flags are detected. Currently, +userfaultfd is the only user of such to sanity check wr-protect bit against +any writable flags. Illegal flag combinations will not directly cause data +corruption in this case immediately, but that will cause read-only data to +be writable, leading to corrupt when the page content is later modified. + Double mapping detection logic ==============================
Makefile +1 -1
@@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 6 PATCHLEVEL = 6 -SUBLEVEL = 46 +SUBLEVEL = 47 EXTRAVERSION = NAME = Hurr durr I'ma ninja sloth
arch/arm64/kvm/hyp/pgtable.c +8 -4
@@ -523,7 +523,7 @@ static int hyp_unmap_walker(const struct kvm_pgtable_visit_ctx *ctx,kvm_clear_pte (ctx->ptep);dsb (ishst); -__tlbi_level (vae2is,__TLBI_VADDR (ctx->addr,0 ), ctx->level); +__tlbi_level (vae2is,__TLBI_VADDR (ctx->addr,0 ),0 ); }else {if (ctx->end - ctx->addr < granule)return -EINVAL ;
@@ -861,9 +861,13 @@ static void stage2_unmap_put_pte(const struct kvm_pgtable_visit_ctx *ctx,if (kvm_pte_valid (ctx->old)) {kvm_clear_pte (ctx->ptep); -if (!stage2_unmap_defer_tlb_flush (pgt)) -kvm_call_hyp (__kvm_tlb_flush_vmid_ipa, mmu, - ctx->addr, ctx->level); +if (kvm_pte_table (ctx->old, ctx->level)) { +kvm_call_hyp (__kvm_tlb_flush_vmid_ipa, mmu, ctx->addr, +0 ); + }else if (!stage2_unmap_defer_tlb_flush (pgt)) { +kvm_call_hyp (__kvm_tlb_flush_vmid_ipa, mmu, ctx->addr, + ctx->level); + } } mm_ops->put_page (ctx->ptep);
arch/loongarch/include/uapi/asm/unistd.h +1 -0
@@ -1,4 +1,5 @@/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#define __ARCH_WANT_NEW_STAT#define __ARCH_WANT_SYS_CLONE#define __ARCH_WANT_SYS_CLONE3
arch/x86/include/asm/pgtable.h +1 -17
@@ -387,23 +387,7 @@ static inline pte_t pte_wrprotect(pte_t pte)#ifdef CONFIG_HAVE_ARCH_USERFAULTFD_WP static inline int pte_uffd_wp (pte_t pte) { -bool wp =pte_flags (pte) & _PAGE_UFFD_WP; - -#ifdef CONFIG_DEBUG_VM -/* -* Having write bit for wr-protect-marked present ptes is fatal, -* because it means the uffd-wp bit will be ignored and write will -* just go through. -* -* Use any chance of pgtable walking to verify this (e.g., when -* page swapped out or being migrated for all purposes). It means -* something is already wrong. Tell the admin even before the -* process crashes. We also nail it with wrong pgtable setup. -*/ -WARN_ON_ONCE (wp &&pte_write (pte)); -#endif - -return wp; +return pte_flags (pte) & _PAGE_UFFD_WP; }static inline pte_t pte_mkuffd_wp (pte_t pte)
drivers/ata/libata-scsi.c +13 -2
@@ -941,8 +941,19 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc) &sense_key, &asc, &ascq);ata_scsi_set_sense (qc->dev, cmd, sense_key, asc, ascq); }else { -/* ATA PASS-THROUGH INFORMATION AVAILABLE */ -ata_scsi_set_sense (qc->dev, cmd,RECOVERED_ERROR ,0 ,0x1D ); +/* +* ATA PASS-THROUGH INFORMATION AVAILABLE +* +* Note: we are supposed to call ata_scsi_set_sense(), which +* respects the D_SENSE bit, instead of unconditionally +* generating the sense data in descriptor format. However, +* because hdparm, hddtemp, and udisks incorrectly assume sense +* data in descriptor format, without even looking at the +* RESPONSE CODE field in the returned sense data (to see which +* format the returned sense data is in), we are stuck with +* being bug compatible with older kernels. +*/ +scsi_build_sense (cmd,1 ,RECOVERED_ERROR ,0 ,0x1D ); } }
drivers/isdn/mISDN/socket.c +5 -5
@@ -401,23 +401,23 @@ data_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) }static int data_sock_setsockopt (struct socket *sock,int level,int optname, -sockptr_t optval,unsigned int len) +sockptr_t optval,unsigned int optlen) {struct sock *sk = sock->sk;int err =0 , opt =0 ;if (*debug &DEBUG_SOCKET )printk (KERN_DEBUG "%s(%p, %d, %x, optval, %d)\n" , __func__, sock, - level, optname, len); + level, optname, optlen);lock_sock (sk);switch (optname) {case MISDN_TIME_STAMP : -if (copy_from_sockptr (&opt, optval,sizeof (int ))) { - err = -EFAULT ; + err =copy_safe_from_sockptr (&opt,sizeof (opt), + optval, optlen); +if (err)break ; - }if (opt)_pms (sk)->cmask |=MISDN_TIME_STAMP ;
drivers/media/usb/dvb-usb/dvb-usb-init.c +4 -31
@@ -23,40 +23,11 @@ static int dvb_usb_force_pid_filter_usage;module_param_named (force_pid_filter_usage, dvb_usb_force_pid_filter_usage, int,0444 );MODULE_PARM_DESC (force_pid_filter_usage,"force all dvb-usb-devices to use a PID filter, if any (default: 0)." ); -static int dvb_usb_check_bulk_endpoint (struct dvb_usb_device *d,u8 endpoint) -{ -if (endpoint) { -int ret; - - ret =usb_pipe_type_check (d->udev,usb_sndbulkpipe (d->udev, endpoint)); -if (ret) -return ret; - ret =usb_pipe_type_check (d->udev,usb_rcvbulkpipe (d->udev, endpoint)); -if (ret) -return ret; - } -return 0 ; -} - -static void dvb_usb_clear_halt (struct dvb_usb_device *d,u8 endpoint) -{ -if (endpoint) { -usb_clear_halt (d->udev,usb_sndbulkpipe (d->udev, endpoint)); -usb_clear_halt (d->udev,usb_rcvbulkpipe (d->udev, endpoint)); - } -} -static int dvb_usb_adapter_init (struct dvb_usb_device *d,short *adapter_nrs) {struct dvb_usb_adapter *adap;int ret, n, o; - ret =dvb_usb_check_bulk_endpoint (d, d->props.generic_bulk_ctrl_endpoint); -if (ret) -return ret; - ret =dvb_usb_check_bulk_endpoint (d, d->props.generic_bulk_ctrl_endpoint_response); -if (ret) -return ret;for (n =0 ; n < d->props.num_adapters; n++) { adap = &d->adapter[n]; adap->dev = d;
@@ -132,8 +103,10 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)* when reloading the driver w/o replugging the device * sometimes a timeout occurs, this helps */ -dvb_usb_clear_halt (d, d->props.generic_bulk_ctrl_endpoint); -dvb_usb_clear_halt (d, d->props.generic_bulk_ctrl_endpoint_response); +if (d->props.generic_bulk_ctrl_endpoint !=0 ) { +usb_clear_halt (d->udev,usb_sndbulkpipe (d->udev, d->props.generic_bulk_ctrl_endpoint)); +usb_clear_halt (d->udev,usb_rcvbulkpipe (d->udev, d->props.generic_bulk_ctrl_endpoint)); + }return 0 ;
drivers/net/ppp/pppoe.c +9 -14
@@ -1007,26 +1007,21 @@ static int pppoe_recvmsg(struct socket *sock, struct msghdr *m,struct sk_buff *skb;int error =0 ; -if (sk->sk_state &PPPOX_BOUND ) { - error = -EIO ; - goto end; - } +if (sk->sk_state &PPPOX_BOUND ) +return -EIO ; skb =skb_recv_datagram (sk, flags, &error); -if (error <0 ) - goto end; +if (!skb) +return error; -if (skb) { - total_len =min_t (size_t, total_len, skb->len); - error =skb_copy_datagram_msg (skb,0 , m, total_len); -if (error ==0 ) { -consume_skb (skb); -return total_len; - } + total_len =min_t (size_t, total_len, skb->len); + error =skb_copy_datagram_msg (skb,0 , m, total_len); +if (error ==0 ) { +consume_skb (skb); +return total_len; }kfree_skb (skb); -end:return error; }
drivers/nvme/host/pci.c +7 -0
@@ -2931,6 +2931,13 @@ static unsigned long check_vendor_combination_bug(struct pci_dev *pdev)return NVME_QUIRK_FORCE_NO_SIMPLE_SUSPEND ; } +/* +* NVMe SSD drops off the PCIe bus after system idle +* for 10 hours on a Lenovo N60z board. +*/ +if (dmi_match (DMI_BOARD_NAME ,"LXKT-ZXEG-N6" )) +return NVME_QUIRK_NO_APST ; +return 0 ; }
fs/binfmt_flat.c +3 -1
@@ -72,8 +72,10 @@#ifdef CONFIG_BINFMT_FLAT_NO_DATA_START_OFFSET #define DATA_START_OFFSET_WORDS (0) +#define MAX_SHARED_LIBS_UPDATE (0)#else #define DATA_START_OFFSET_WORDS (MAX_SHARED_LIBS) +#define MAX_SHARED_LIBS_UPDATE (MAX_SHARED_LIBS)#endif struct lib_info {
@@ -880,7 +882,7 @@ static int load_flat_binary(struct linux_binprm *bprm)return res;/* Update data segment pointers for all libraries */ -for (i =0 ; i <MAX_SHARED_LIBS ; i++) { +for (i =0 ; i <MAX_SHARED_LIBS_UPDATE ; i++) {if (!libinfo.lib_list[i].loaded)continue ;for (j =0 ; j <MAX_SHARED_LIBS ; j++) {
fs/buffer.c +2 -0
@@ -2179,6 +2179,8 @@ static void __block_commit_write(struct folio *folio, size_t from, size_t to)struct buffer_head *bh, *head; bh = head =folio_buffers (folio); +if (!bh) +return ; blocksize = bh->b_size; block_start =0 ;
fs/cramfs/inode.c +1 -1
@@ -495,7 +495,7 @@ static void cramfs_kill_sb(struct super_block *sb) sb->s_mtd =NULL ; }else if (IS_ENABLED (CONFIG_CRAMFS_BLOCKDEV ) && sb->s_bdev) {sync_blockdev (sb->s_bdev); -blkdev_put (sb->s_bdev, sb); +bdev_release (sb->s_bdev_handle); }kfree (sbi); }
fs/erofs/decompressor.c +1 -7
@@ -248,15 +248,9 @@ static int z_erofs_lz4_decompress_mem(struct z_erofs_lz4_decompress_ctx *ctx,if (ret != rq->outputsize) {erofs_err (rq->sb,"failed to decompress %d in[%u, %u] out[%u]" , ret, rq->inputsize, inputmargin, rq->outputsize); - -print_hex_dump (KERN_DEBUG ,"[ in]: " ,DUMP_PREFIX_OFFSET , -16 ,1 , src + inputmargin, rq->inputsize, true); -print_hex_dump (KERN_DEBUG ,"[out]: " ,DUMP_PREFIX_OFFSET , -16 ,1 , out, rq->outputsize, true); -if (ret >=0 )memset (out + ret,0 , rq->outputsize - ret); - ret = -EIO ; + ret = -EFSCORRUPTED ; }else { ret =0 ; }
fs/exec.c +7 -1
@@ -1609,6 +1609,7 @@ static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file)unsigned int mode;vfsuid_t vfsuid;vfsgid_t vfsgid; +int err;if (!mnt_may_suid (file->f_path.mnt))return ;
@@ -1625,12 +1626,17 @@ static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file)/* Be careful if suid/sgid is set */ inode_lock (inode); -/* reload atomically mode/uid/gid now that lock held */ +/* Atomically reload and check mode/uid/gid now that lock held. */ mode = inode->i_mode; vfsuid =i_uid_into_vfsuid (idmap, inode); vfsgid =i_gid_into_vfsgid (idmap, inode); + err =inode_permission (idmap, inode,MAY_EXEC );inode_unlock (inode); +/* Did the exec bit vanish out from under us? Give up. */ +if (err) +return ; +/* We ignore suid/sgid if there are no mappings for them in the ns */ if (!vfsuid_has_mapping (bprm->cred->user_ns, vfsuid) || !vfsgid_has_mapping (bprm->cred->user_ns, vfsgid))
fs/ext4/inode.c +15 -9
@@ -2966,23 +2966,29 @@ static int ext4_da_should_update_i_disksize(struct folio *folio,static int ext4_da_do_write_end (struct address_space *mapping,loff_t pos,unsigned len,unsigned copied, -struct page *page) +struct folio *folio) {struct inode *inode = mapping->host;loff_t old_size = inode->i_size;bool disksize_changed = false;loff_t new_i_size; +if (unlikely (!folio_buffers (folio))) { +folio_unlock (folio); +folio_put (folio); +return -EIO ; + }/* * block_write_end() will mark the inode as dirty with I_DIRTY_PAGES * flag, which all that's needed to trigger page writeback. */ - copied =block_write_end (NULL , mapping, pos, len, copied, page,NULL ); + copied =block_write_end (NULL , mapping, pos, len, copied, + &folio->page,NULL ); new_i_size = pos + copied;/* -* It's important to update i_size while still holding page lock, -* because page writeout could otherwise come in and zero beyond +* It's important to update i_size while still holding folio lock, +* because folio writeout could otherwise come in and zero beyond * i_size. * * Since we are holding inode lock, we are sure i_disksize <=
@@ -3000,14 +3006,14 @@ static int ext4_da_do_write_end(struct address_space *mapping,i_size_write (inode, new_i_size); end = (new_i_size -1 ) & (PAGE_SIZE -1 ); -if (copied &&ext4_da_should_update_i_disksize (page_folio (page), end)) { +if (copied &&ext4_da_should_update_i_disksize (folio, end)) {ext4_update_i_disksize (inode, new_i_size); disksize_changed = true; } } -unlock_page (page); -put_page (page); +folio_unlock (folio); +folio_put (folio);if (old_size < pos)pagecache_isize_extended (inode, old_size, pos);
@@ -3046,10 +3052,10 @@ static int ext4_da_write_end(struct file *file,return ext4_write_inline_data_end (inode, pos, len, copied, folio); -if (unlikely (copied < len) && !PageUptodate (page)) +if (unlikely (copied < len) && !folio_test_uptodate (folio)) copied =0 ; -return ext4_da_do_write_end (mapping, pos, len, copied, &folio->page); +return ext4_da_do_write_end (mapping, pos, len, copied, folio); }/*
fs/ext4/xattr.c +73 -82
270 lines not on this page · raw message
fs/f2fs/extent_cache.c +19 -29
88 lines not on this page · raw message
fs/f2fs/f2fs.h +1 -1
@@ -4189,7 +4189,7 @@ void f2fs_leave_shrinker(struct f2fs_sb_info *sbi);/* * extent_cache.c */ -bool sanity_check_extent_cache (struct inode *inode); +bool sanity_check_extent_cache (struct inode *inode,struct page *ipage);void f2fs_init_extent_tree (struct inode *inode);void f2fs_drop_extent_tree (struct inode *inode);void f2fs_destroy_extent_node (struct inode *inode);
fs/f2fs/gc.c +10 -0
@@ -1563,6 +1563,16 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,continue ; } +if (f2fs_has_inline_data (inode)) { +iput (inode); +set_sbi_flag (sbi,SBI_NEED_FSCK ); +f2fs_err_ratelimited (sbi, +"inode %lx has both inline_data flag and " +"data block, nid=%u, ofs_in_node=%u" , + inode->i_ino, dni.nid, ofs_in_node); +continue ; + } + err =f2fs_gc_pinned_control (inode, gc_type, segno);if (err == -EAGAIN ) {iput (inode);
fs/f2fs/inode.c +5 -5
@@ -511,16 +511,16 @@ static int do_read_inode(struct inode *inode)init_idisk_time (inode); -/* Need all the flag bits */ -f2fs_init_read_extent_tree (inode, node_page); -f2fs_init_age_extent_tree (inode); - -if (!sanity_check_extent_cache (inode)) { +if (!sanity_check_extent_cache (inode, node_page)) {f2fs_put_page (node_page,1 );f2fs_handle_error (sbi,ERROR_CORRUPTED_INODE );return -EFSCORRUPTED ; } +/* Need all the flag bits */ +f2fs_init_read_extent_tree (inode, node_page); +f2fs_init_age_extent_tree (inode); +f2fs_put_page (node_page,1 );stat_inc_inline_xattr (inode);
fs/fhandle.c +3 -3
@@ -40,7 +40,7 @@ static long do_sys_name_to_handle(const struct path *path,if (f_handle.handle_bytes >MAX_HANDLE_SZ )return -EINVAL ; - handle =kzalloc (sizeof (struct file_handle ) + f_handle.handle_bytes, + handle =kzalloc (struct_size (handle, f_handle, f_handle.handle_bytes),GFP_KERNEL );if (!handle)return -ENOMEM ;
@@ -75,7 +75,7 @@ static long do_sys_name_to_handle(const struct path *path,/* copy the mount id */ if (put_user (real_mount (path->mnt)->mnt_id, mnt_id) ||copy_to_user (ufh, handle, -sizeof (struct file_handle ) + handle_bytes)) +struct_size (handle, f_handle, handle_bytes))) retval = -EFAULT ;kfree (handle);return retval;
@@ -196,7 +196,7 @@ static int handle_to_path(int mountdirfd, struct file_handle __user *ufh, retval = -EINVAL ; goto out_err; } - handle =kmalloc (sizeof (struct file_handle ) + f_handle.handle_bytes, + handle =kmalloc (struct_size (handle, f_handle, f_handle.handle_bytes),GFP_KERNEL );if (!handle) { retval = -ENOMEM ;
fs/jfs/jfs_dmap.c +2 -0
@@ -1626,6 +1626,8 @@ s64 dbDiscardAG(struct inode *ip, int agno, s64 minlen) }else if (rc == -ENOSPC ) {/* search for next smaller log2 block */ l2nb =BLKSTOL2 (nblocks) -1 ; +if (unlikely (l2nb <0 )) +break ; nblocks =1LL << l2nb; }else {/* Trim any already allocated blocks */
fs/jfs/jfs_dtree.c +2 -0
@@ -834,6 +834,8 @@ int dtInsert(tid_t tid, struct inode *ip,* the full page. */ DT_GETSEARCH (ip, btstack->top, bn, mp, p, index); +if (p->header.freelist ==0 ) +return -EINVAL ;/* * insert entry for new key
fs/jfs/jfs_logmgr.c +19 -14
@@ -1058,7 +1058,7 @@ void jfs_syncpt(struct jfs_log *log, int hard_sync)int lmLogOpen (struct super_block *sb) {int rc; -struct block_device *bdev; +struct bdev_handle *bdev_handle;struct jfs_log *log;struct jfs_sb_info *sbi =JFS_SBI (sb);
@@ -1070,7 +1070,7 @@ int lmLogOpen(struct super_block *sb)mutex_lock (&jfs_log_mutex);list_for_each_entry (log, &jfs_external_logs, journal_list) { -if (log->bdev->bd_dev == sbi->logdev) { +if (log->bdev_handle->bdev->bd_dev == sbi->logdev) {if (!uuid_equal (&log->uuid, &sbi->loguuid)) {jfs_warn ("wrong uuid on JFS journal" );mutex_unlock (&jfs_log_mutex);
@@ -1100,14 +1100,14 @@ int lmLogOpen(struct super_block *sb)* file systems to log may have n-to-1 relationship; */ - bdev =blkdev_get_by_dev (sbi->logdev,BLK_OPEN_READ |BLK_OPEN_WRITE , - log,NULL ); -if (IS_ERR (bdev)) { - rc =PTR_ERR (bdev); + bdev_handle =bdev_open_by_dev (sbi->logdev, +BLK_OPEN_READ |BLK_OPEN_WRITE , log,NULL ); +if (IS_ERR (bdev_handle)) { + rc =PTR_ERR (bdev_handle); goto free; } - log->bdev = bdev; + log->bdev_handle = bdev_handle;uuid_copy (&log->uuid, &sbi->loguuid);/*
@@ -1141,7 +1141,7 @@ int lmLogOpen(struct super_block *sb)lbmLogShutdown (log); close:/* close external log device */ -blkdev_put (bdev, log); +bdev_release (bdev_handle); free:/* free log descriptor */ mutex_unlock (&jfs_log_mutex);
@@ -1162,7 +1162,7 @@ static int open_inline_log(struct super_block *sb)init_waitqueue_head (&log->syncwait);set_bit (log_INLINELOG, &log->flag); - log->bdev = sb->s_bdev; + log->bdev_handle = sb->s_bdev_handle; log->base =addressPXD (&JFS_SBI (sb)->logpxd); log->size =lengthPXD (&JFS_SBI (sb)->logpxd) >> (L2LOGPSIZE - sb->s_blocksize_bits);
@@ -1436,7 +1436,7 @@ int lmLogClose(struct super_block *sb) {struct jfs_sb_info *sbi =JFS_SBI (sb);struct jfs_log *log = sbi->log; -struct block_device *bdev; +struct bdev_handle *bdev_handle;int rc =0 ;jfs_info ("lmLogClose: log:0x%p" , log);
@@ -1482,10 +1482,10 @@ int lmLogClose(struct super_block *sb)* external log as separate logical volume */ list_del (&log->journal_list); - bdev = log->bdev; + bdev_handle = log->bdev_handle; rc =lmLogShutdown (log); -blkdev_put (bdev, log); +bdev_release (bdev_handle);kfree (log);
@@ -1972,7 +1972,7 @@ static int lbmRead(struct jfs_log * log, int pn, struct lbuf ** bpp) bp->l_flag |= lbmREAD; - bio =bio_alloc (log->bdev,1 ,REQ_OP_READ ,GFP_NOFS ); + bio =bio_alloc (log->bdev_handle->bdev,1 ,REQ_OP_READ ,GFP_NOFS ); bio->bi_iter.bi_sector = bp->l_blkno << (log->l2bsize -9 );__bio_add_page (bio, bp->l_page,LOGPSIZE , bp->l_offset);BUG_ON (bio->bi_iter.bi_size !=LOGPSIZE );
@@ -2110,10 +2110,15 @@ static void lbmStartIO(struct lbuf * bp) {struct bio *bio;struct jfs_log *log = bp->l_log; +struct block_device *bdev =NULL ;jfs_info ("lbmStartIO" ); - bio =bio_alloc (log->bdev,1 ,REQ_OP_WRITE |REQ_SYNC ,GFP_NOFS ); +if (!log->no_integrity) + bdev = log->bdev_handle->bdev; + + bio =bio_alloc (bdev,1 ,REQ_OP_WRITE |REQ_SYNC , +GFP_NOFS ); bio->bi_iter.bi_sector = bp->l_blkno << (log->l2bsize -9 );__bio_add_page (bio, bp->l_page,LOGPSIZE , bp->l_offset);BUG_ON (bio->bi_iter.bi_size !=LOGPSIZE );
fs/jfs/jfs_logmgr.h +1 -1
@@ -356,7 +356,7 @@ struct jfs_log {* before writing syncpt. */ struct list_head journal_list;/* Global list */ -struct block_device *bdev;/* 4: log lv pointer */ +struct bdev_handle *bdev_handle;/* 4: log lv pointer */ int serial;/* 4: log mount serial number */ s64 base;/* @8: log extent address (inline log ) */
fs/jfs/jfs_mount.c +2 -1
@@ -430,7 +430,8 @@ int updateSuper(struct super_block *sb, uint state)if (state ==FM_MOUNT ) {/* record log's dev_t and mount serial number */ - j_sb->s_logdev =cpu_to_le32 (new_encode_dev (sbi->log->bdev->bd_dev)); + j_sb->s_logdev =cpu_to_le32 ( +new_encode_dev (sbi->log->bdev_handle->bdev->bd_dev)); j_sb->s_logserial =cpu_to_le32 (sbi->log->serial); }else if (state ==FM_CLEAN ) {/*
fs/lockd/svc.c +0 -3
@@ -712,8 +712,6 @@ static const struct svc_version *nlmsvc_version[] = {#endif }; -static struct svc_stat nlmsvc_stats; -#define NLM_NRVERS ARRAY_SIZE(nlmsvc_version)static struct svc_program nlmsvc_program = { .pg_prog =NLM_PROGRAM ,/* program number */
@@ -721,7 +719,6 @@ static struct svc_program nlmsvc_program = { .pg_vers = nlmsvc_version, /* version table */ .pg_name = "lockd", /* service name */ .pg_class = "nfsd", /* share authentication with nfsd */ - .pg_stats = &nlmsvc_stats, /* stats table */ .pg_authenticate = &lockd_authenticate, /* export authentication */ .pg_init_request = svc_generic_init_request, .pg_rpcbind_set = svc_generic_rpcbind_set,
fs/nfs/callback.c +0 -3
@@ -399,15 +399,12 @@ static const struct svc_version *nfs4_callback_version[] = { [4] = &nfs4_callback_version4, }; -static struct svc_stat nfs4_callback_stats; -static struct svc_program nfs4_callback_program = { .pg_prog =NFS4_CALLBACK ,/* RPC service number */ .pg_nvers =ARRAY_SIZE (nfs4_callback_version),/* Number of entries */ .pg_vers = nfs4_callback_version,/* version table */ .pg_name ="NFSv4 callback" ,/* service name */ .pg_class ="nfs" ,/* authentication class */ - .pg_stats = &nfs4_callback_stats, .pg_authenticate = nfs_callback_authenticate, .pg_init_request = svc_generic_init_request, .pg_rpcbind_set = svc_generic_rpcbind_set,
fs/nfsd/cache.h +0 -2
@@ -80,8 +80,6 @@ enum {int nfsd_drc_slab_create (void );void nfsd_drc_slab_free (void ); -int nfsd_net_reply_cache_init (struct nfsd_net *nn); -void nfsd_net_reply_cache_destroy (struct nfsd_net *nn);int nfsd_reply_cache_init (struct nfsd_net *);void nfsd_reply_cache_shutdown (struct nfsd_net *); int nfsd_cache_lookup(struct svc_rqst *rqstp, unsigned int start,
fs/nfsd/export.c +23 -9
@@ -339,12 +339,16 @@ static int export_stats_init(struct export_stats *stats)static void export_stats_reset (struct export_stats *stats) { -nfsd_percpu_counters_reset (stats->counter,EXP_STATS_COUNTERS_NUM ); +if (stats) +nfsd_percpu_counters_reset (stats->counter, +EXP_STATS_COUNTERS_NUM ); }static void export_stats_destroy (struct export_stats *stats) { -nfsd_percpu_counters_destroy (stats->counter,EXP_STATS_COUNTERS_NUM ); +if (stats) +nfsd_percpu_counters_destroy (stats->counter, +EXP_STATS_COUNTERS_NUM ); }static void svc_export_put (struct kref *ref)
@@ -353,7 +357,8 @@ static void svc_export_put(struct kref *ref)path_put (&exp->ex_path);auth_domain_put (exp->ex_client);nfsd4_fslocs_free (&exp->ex_fslocs); -export_stats_destroy (&exp->ex_stats); +export_stats_destroy (exp->ex_stats); +kfree (exp->ex_stats);kfree (exp->ex_uuid);kfree_rcu (exp, ex_rcu); }
@@ -767,13 +772,15 @@ static int svc_export_show(struct seq_file *m,seq_putc (m,'\t' );seq_escape (m, exp->ex_client->name," \t\n\\" );if (export_stats) { -seq_printf (m,"\t%lld\n" , exp->ex_stats.start_time); +struct percpu_counter *counter = exp->ex_stats->counter; + +seq_printf (m,"\t%lld\n" , exp->ex_stats->start_time);seq_printf (m,"\tfh_stale: %lld\n" , -percpu_counter_sum_positive (&exp->ex_stats.counter[EXP_STATS_FH_STALE ])); +percpu_counter_sum_positive (&counter[EXP_STATS_FH_STALE ]));seq_printf (m,"\tio_read: %lld\n" , -percpu_counter_sum_positive (&exp->ex_stats.counter[EXP_STATS_IO_READ ])); +percpu_counter_sum_positive (&counter[EXP_STATS_IO_READ ]));seq_printf (m,"\tio_write: %lld\n" , -percpu_counter_sum_positive (&exp->ex_stats.counter[EXP_STATS_IO_WRITE ])); +percpu_counter_sum_positive (&counter[EXP_STATS_IO_WRITE ]));seq_putc (m,'\n' );return 0 ; }
@@ -819,7 +826,7 @@ static void svc_export_init(struct cache_head *cnew, struct cache_head *citem) new->ex_layout_types =0 ; new->ex_uuid =NULL ; new->cd = item->cd; -export_stats_reset (&new->ex_stats); +export_stats_reset (new->ex_stats); }static void export_update (struct cache_head *cnew,struct cache_head *citem)
@@ -856,7 +863,14 @@ static struct cache_head *svc_export_alloc(void)if (!i)return NULL ; -if (export_stats_init (&i->ex_stats)) { + i->ex_stats =kmalloc (sizeof (*(i->ex_stats)),GFP_KERNEL ); +if (!i->ex_stats) { +kfree (i); +return NULL ; + } + +if (export_stats_init (i->ex_stats)) { +kfree (i->ex_stats);kfree (i);return NULL ; }
fs/nfsd/export.h +2 -2
@@ -64,10 +64,10 @@ struct svc_export {struct cache_head h;struct auth_domain * ex_client;int ex_flags; +int ex_fsid;struct path ex_path;kuid_t ex_anon_uid;kgid_t ex_anon_gid; -int ex_fsid;unsigned char * ex_uuid;/* 16 byte fsid */ struct nfsd4_fs_locations ex_fslocs;uint32_t ex_nflavors;
@@ -76,8 +76,8 @@ struct svc_export {struct nfsd4_deviceid_map *ex_devid_map;struct cache_detail *cd;struct rcu_head ex_rcu; -struct export_stats ex_stats;unsigned long ex_xprtsec_modes; +struct export_stats *ex_stats; };/* an "export key" (expkey) maps a filehandlefragement to an
fs/nfsd/netns.h +21 -4
@@ -11,8 +11,10 @@#include <net/net_namespace.h> #include <net/netns/generic.h> #include <linux/filelock.h> +#include <linux/nfs4.h> #include <linux/percpu_counter.h> #include <linux/siphash.h> +#include <linux/sunrpc/stats.h> /* Hash tables for nfs4_clientid state */ #define CLIENT_HASH_BITS 4
@@ -26,10 +28,22 @@ struct nfsd4_client_tracking_ops;enum {/* cache misses due only to checksum comparison failures */ -NFSD_NET_PAYLOAD_MISSES , +NFSD_STATS_PAYLOAD_MISSES ,/* amount of memory (in bytes) currently consumed by the DRC */ -NFSD_NET_DRC_MEM_USAGE , -NFSD_NET_COUNTERS_NUM +NFSD_STATS_DRC_MEM_USAGE , +NFSD_STATS_RC_HITS ,/* repcache hits */ +NFSD_STATS_RC_MISSES ,/* repcache misses */ +NFSD_STATS_RC_NOCACHE ,/* uncached reqs */ +NFSD_STATS_FH_STALE ,/* FH stale error */ +NFSD_STATS_IO_READ ,/* bytes returned to read requests */ +NFSD_STATS_IO_WRITE ,/* bytes passed in write requests */ +#ifdef CONFIG_NFSD_V4 +NFSD_STATS_FIRST_NFS4_OP ,/* count of individual nfsv4 operations */ +NFSD_STATS_LAST_NFS4_OP =NFSD_STATS_FIRST_NFS4_OP +LAST_NFS4_OP , +#define NFSD_STATS_NFS4_OP(op) (NFSD_STATS_FIRST_NFS4_OP + (op)) +NFSD_STATS_WDELEG_GETATTR ,/* count of getattr conflict with wdeleg */ +#endif +NFSD_STATS_COUNTERS_NUM };/*
@@ -169,7 +183,10 @@ struct nfsd_net {atomic_t num_drc_entries;/* Per-netns stats counters */ -struct percpu_counter counter[NFSD_NET_COUNTERS_NUM ]; +struct percpu_counter counter[NFSD_STATS_COUNTERS_NUM ]; + +/* sunrpc svc stats */ +struct svc_stat nfsd_svcstats;/* longest hash chain seen */ unsigned int longest_chain;
fs/nfsd/nfs4proc.c +3 -3
@@ -2478,10 +2478,10 @@ nfsd4_proc_null(struct svc_rqst *rqstp)return rpc_success; } -static inline void nfsd4_increment_op_stats (u32 opnum) +static inline void nfsd4_increment_op_stats (struct nfsd_net *nn,u32 opnum) {if (opnum >=FIRST_NFS4_OP && opnum <=LAST_NFS4_OP ) -percpu_counter_inc (&nfsdstats.counter[NFSD_STATS_NFS4_OP (opnum)]); +percpu_counter_inc (&nn->counter[NFSD_STATS_NFS4_OP (opnum)]); }static const struct nfsd4_operation nfsd4_ops[];
@@ -2756,7 +2756,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) status, nfsd4_op_name(op->opnum));nfsd4_cstate_clear_replay (cstate); -nfsd4_increment_op_stats (op->opnum); +nfsd4_increment_op_stats (nn, op->opnum); }fh_put (current_fh);
fs/nfsd/nfs4state.c +2 -1
@@ -8422,6 +8422,7 @@ __be32 nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode) { __be32 status; +struct nfsd_net *nn =net_generic (SVC_NET (rqstp), nfsd_net_id);struct file_lock_context *ctx;struct file_lock *fl;struct nfs4_delegation *dp;
@@ -8451,7 +8452,7 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode) } break_lease:spin_unlock (&ctx->flc_lock); -nfsd_stats_wdeleg_getattr_inc (); +nfsd_stats_wdeleg_getattr_inc (nn); status =nfserrno (nfsd_open_break_lease (inode,NFSD_MAY_READ ));if (status != nfserr_jukebox || !nfsd_wait_for_delegreturn (rqstp, inode))
fs/nfsd/nfscache.c +9 -31
@@ -176,27 +176,6 @@ void nfsd_drc_slab_free(void)kmem_cache_destroy (drc_slab); } -/** -* nfsd_net_reply_cache_init - per net namespace reply cache set-up -* @nn: nfsd_net being initialized -* -* Returns zero on succes; otherwise a negative errno is returned. -*/ -int nfsd_net_reply_cache_init (struct nfsd_net *nn) -{ -return nfsd_percpu_counters_init (nn->counter,NFSD_NET_COUNTERS_NUM ); -} - -/** -* nfsd_net_reply_cache_destroy - per net namespace reply cache tear-down -* @nn: nfsd_net being freed -* -*/ -void nfsd_net_reply_cache_destroy (struct nfsd_net *nn) -{ -nfsd_percpu_counters_destroy (nn->counter,NFSD_NET_COUNTERS_NUM ); -} -int nfsd_reply_cache_init (struct nfsd_net *nn) {unsigned int hashsize;
@@ -502,7 +481,7 @@ nfsd_cache_insert(struct nfsd_drc_bucket *b, struct nfsd_cacherep *key,int nfsd_cache_lookup (struct svc_rqst *rqstp,unsigned int start,unsigned int len,struct nfsd_cacherep **cacherep) { -struct nfsd_net *nn; +struct nfsd_net *nn =net_generic (SVC_NET (rqstp), nfsd_net_id);struct nfsd_cacherep *rp, *found;__wsum csum;struct nfsd_drc_bucket *b;
@@ -512,7 +491,7 @@ int nfsd_cache_lookup(struct svc_rqst *rqstp, unsigned int start,int rtn =RC_DOIT ;if (type ==RC_NOCACHE ) { -nfsd_stats_rc_nocache_inc (); +nfsd_stats_rc_nocache_inc (nn); goto out; }
@@ -522,7 +501,6 @@ int nfsd_cache_lookup(struct svc_rqst *rqstp, unsigned int start,* Since the common case is a cache miss followed by an insert, * preallocate an entry. */ - nn =net_generic (SVC_NET (rqstp), nfsd_net_id); rp =nfsd_cacherep_alloc (rqstp, csum, nn);if (!rp) goto out;
@@ -540,7 +518,7 @@ int nfsd_cache_lookup(struct svc_rqst *rqstp, unsigned int start, freed =nfsd_cacherep_dispose (&dispose);trace_nfsd_drc_gc (nn, freed); -nfsd_stats_rc_misses_inc (); +nfsd_stats_rc_misses_inc (nn);atomic_inc (&nn->num_drc_entries);nfsd_stats_drc_mem_usage_add (nn,sizeof (*rp)); goto out;
@@ -548,7 +526,7 @@ int nfsd_cache_lookup(struct svc_rqst *rqstp, unsigned int start, found_entry:/* We found a matching entry which is either in progress or done. */ nfsd_reply_cache_free_locked (NULL , rp, nn); -nfsd_stats_rc_hits_inc (); +nfsd_stats_rc_hits_inc (nn); rtn =RC_DROPIT ; rp = found;
@@ -690,15 +668,15 @@ int nfsd_reply_cache_stats_show(struct seq_file *m, void *v) atomic_read(&nn->num_drc_entries));seq_printf (m,"hash buckets: %u\n" ,1 << nn->maskbits);seq_printf (m,"mem usage: %lld\n" , -percpu_counter_sum_positive (&nn->counter[NFSD_NET_DRC_MEM_USAGE ])); +percpu_counter_sum_positive (&nn->counter[NFSD_STATS_DRC_MEM_USAGE ]));seq_printf (m,"cache hits: %lld\n" , -percpu_counter_sum_positive (&nfsdstats.counter[NFSD_STATS_RC_HITS ])); +percpu_counter_sum_positive (&nn->counter[NFSD_STATS_RC_HITS ]));seq_printf (m,"cache misses: %lld\n" , -percpu_counter_sum_positive (&nfsdstats.counter[NFSD_STATS_RC_MISSES ])); +percpu_counter_sum_positive (&nn->counter[NFSD_STATS_RC_MISSES ]));seq_printf (m,"not cached: %lld\n" , -percpu_counter_sum_positive (&nfsdstats.counter[NFSD_STATS_RC_NOCACHE ])); +percpu_counter_sum_positive (&nn->counter[NFSD_STATS_RC_NOCACHE ]));seq_printf (m,"payload misses: %lld\n" , -percpu_counter_sum_positive (&nn->counter[NFSD_NET_PAYLOAD_MISSES ])); +percpu_counter_sum_positive (&nn->counter[NFSD_STATS_PAYLOAD_MISSES ]));seq_printf (m,"longest chain len: %u\n" , nn->longest_chain);seq_printf (m,"cachesize at longest: %u\n" , nn->longest_chain_cachesize);return 0 ;
fs/nfsd/nfsctl.c +7 -9
@@ -1524,14 +1524,17 @@ static __net_init int nfsd_net_init(struct net *net) retval =nfsd_idmap_init (net);if (retval) goto out_idmap_error; - retval =nfsd_net_reply_cache_init (nn); + retval =nfsd_stat_counters_init (nn);if (retval) goto out_repcache_error; +memset (&nn->nfsd_svcstats,0 ,sizeof (nn->nfsd_svcstats)); + nn->nfsd_svcstats.program = &nfsd_program; nn->nfsd_versions =NULL ; nn->nfsd4_minorversions =NULL ;nfsd4_init_leases_net (nn);get_random_bytes (&nn->siphash_key,sizeof (nn->siphash_key));seqlock_init (&nn->writeverf_lock); +nfsd_proc_stat_init (net);return 0 ;
@@ -1552,7 +1555,8 @@ static __net_exit void nfsd_net_exit(struct net *net) {struct nfsd_net *nn =net_generic (net, nfsd_net_id); -nfsd_net_reply_cache_destroy (nn); +nfsd_proc_stat_shutdown (net); +nfsd_stat_counters_destroy (nn);nfsd_idmap_shutdown (net);nfsd_export_shutdown (net);nfsd_netns_free_versions (nn);
@@ -1575,12 +1579,9 @@ static int __init init_nfsd(void) retval =nfsd4_init_pnfs ();if (retval) goto out_free_slabs; - retval =nfsd_stat_init ();/* Statistics */ -if (retval) - goto out_free_pnfs; retval =nfsd_drc_slab_create ();if (retval) - goto out_free_stat; + goto out_free_pnfs;nfsd_lockd_init ();/* lockd->nfsd callbacks */ retval =create_proc_exports_entry ();if (retval)
@@ -1610,8 +1611,6 @@ static int __init init_nfsd(void) out_free_lockd:nfsd_lockd_shutdown ();nfsd_drc_slab_free (); -out_free_stat: -nfsd_stat_shutdown (); out_free_pnfs:nfsd4_exit_pnfs (); out_free_slabs:
@@ -1628,7 +1627,6 @@ static void __exit exit_nfsd(void)nfsd_drc_slab_free ();remove_proc_entry ("fs/nfs/exports" ,NULL );remove_proc_entry ("fs/nfs" ,NULL ); -nfsd_stat_shutdown ();nfsd_lockd_shutdown ();nfsd4_free_slabs ();nfsd4_exit_pnfs ();
fs/nfsd/nfsd.h +1 -0
@@ -69,6 +69,7 @@ extern struct mutex nfsd_mutex;extern spinlock_t nfsd_drc_lock;extern unsigned long nfsd_drc_max_mem;extern unsigned long nfsd_drc_mem_used; +extern atomic_t nfsd_th_cnt;/* number of available threads */ extern const struct seq_operations nfs_exports_op;
fs/nfsd/nfsfh.c +2 -1
@@ -327,6 +327,7 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)__be32 fh_verify (struct svc_rqst *rqstp,struct svc_fh *fhp,umode_t type,int access) { +struct nfsd_net *nn =net_generic (SVC_NET (rqstp), nfsd_net_id);struct svc_export *exp =NULL ;struct dentry *dentry;__be32 error;
@@ -395,7 +396,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access) out:trace_nfsd_fh_verify_err (rqstp, fhp, type, access, error);if (error == nfserr_stale) -nfsd_stats_fh_stale_inc (exp); +nfsd_stats_fh_stale_inc (nn, exp);return error; }
fs/nfsd/nfssvc.c +5 -9
@@ -34,6 +34,7 @@#define NFSDDBG_FACILITY NFSDDBG_SVC +atomic_t nfsd_th_cnt =ATOMIC_INIT (0 );extern struct svc_program nfsd_program;static int nfsd (void *vrqstp);#if defined(CONFIG_NFSD_V2_ACL ) || defined(CONFIG_NFSD_V3_ACL )
@@ -89,7 +90,6 @@ unsigned long nfsd_drc_max_mem;unsigned long nfsd_drc_mem_used;#if defined(CONFIG_NFSD_V2_ACL ) || defined(CONFIG_NFSD_V3_ACL ) -static struct svc_stat nfsd_acl_svcstats;static const struct svc_version *nfsd_acl_version[] = { # if defined(CONFIG_NFSD_V2_ACL) [2] = &nfsd_acl_version2,
@@ -108,15 +108,11 @@ static struct svc_program nfsd_acl_program = { .pg_vers = nfsd_acl_version, .pg_name = "nfsacl", .pg_class = "nfsd", - .pg_stats = &nfsd_acl_svcstats, .pg_authenticate = &svc_set_client, .pg_init_request = nfsd_acl_init_request, .pg_rpcbind_set = nfsd_acl_rpcbind_set, }; -static struct svc_stat nfsd_acl_svcstats = { - .program = &nfsd_acl_program, -};#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */ static const struct svc_version *nfsd_version[] = {
@@ -141,7 +137,6 @@ struct svc_program nfsd_program = { .pg_vers = nfsd_version, /* version table */ .pg_name = "nfsd", /* program name */ .pg_class = "nfsd", /* authentication class */ - .pg_stats = &nfsd_svcstats, /* version table */ .pg_authenticate = &svc_set_client, /* export authentication */ .pg_init_request = nfsd_init_request, .pg_rpcbind_set = nfsd_rpcbind_set,
@@ -675,7 +670,8 @@ int nfsd_create_serv(struct net *net)if (nfsd_max_blksize ==0 ) nfsd_max_blksize =nfsd_get_default_max_blksize ();nfsd_reset_versions (nn); - serv =svc_create_pooled (&nfsd_program, nfsd_max_blksize, nfsd); + serv =svc_create_pooled (&nfsd_program, &nn->nfsd_svcstats, + nfsd_max_blksize, nfsd);if (serv ==NULL )return -ENOMEM ;
@@ -950,7 +946,7 @@ nfsd(void *vrqstp) current->fs->umask =0 ; -atomic_inc (&nfsdstats.th_cnt); +atomic_inc (&nfsd_th_cnt);set_freezable ();
@@ -964,7 +960,7 @@ nfsd(void *vrqstp)svc_recv (rqstp); } -atomic_dec (&nfsdstats.th_cnt); +atomic_dec (&nfsd_th_cnt); out:/* Release the thread */
fs/nfsd/stats.c +22 -32
102 lines not on this page · raw message
fs/nfsd/stats.h +34 -56
128 lines not on this page · raw message
fs/nfsd/vfs.c +4 -2
@@ -985,7 +985,9 @@ static __be32 nfsd_finish_read(struct svc_rqst *rqstp, struct svc_fh *fhp, unsigned long *count, u32 *eof, ssize_t host_err) { if (host_err >= 0) { - nfsd_stats_io_read_add(fhp->fh_export, host_err); + struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); + +nfsd_stats_io_read_add (nn, fhp->fh_export, host_err); *eof =nfsd_eof_on_read (file, offset, host_err, *count); *count = host_err;fsnotify_access (file);
@@ -1168,7 +1170,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf, goto out_nfserr; } *cnt = host_err; -nfsd_stats_io_write_add (exp, *cnt); +nfsd_stats_io_write_add (nn, exp, *cnt);fsnotify_modify (file); host_err =filemap_check_wb_err (file->f_mapping, since);if (host_err <0 )
fs/ntfs3/frecord.c +72 -3
112 lines not on this page · raw message
fs/quota/quota_tree.c +96 -32
259 lines not on this page · raw message
fs/quota/quota_v2.c +9 -6
@@ -166,14 +166,17 @@ static int v2_read_file_info(struct super_block *sb, int type) i_size_read(sb_dqopt(sb)->files[type])); goto out_free; } -if (qinfo->dqi_free_blk >= qinfo->dqi_blocks) { -quota_error (sb,"Free block number too big (%u >= %u)." , - qinfo->dqi_free_blk, qinfo->dqi_blocks); +if (qinfo->dqi_free_blk && (qinfo->dqi_free_blk <=QT_TREEOFF || + qinfo->dqi_free_blk >= qinfo->dqi_blocks)) { +quota_error (sb,"Free block number %u out of range (%u, %u)." , + qinfo->dqi_free_blk,QT_TREEOFF , qinfo->dqi_blocks); goto out_free; } -if (qinfo->dqi_free_entry >= qinfo->dqi_blocks) { -quota_error (sb,"Block with free entry too big (%u >= %u)." , - qinfo->dqi_free_entry, qinfo->dqi_blocks); +if (qinfo->dqi_free_entry && (qinfo->dqi_free_entry <=QT_TREEOFF || + qinfo->dqi_free_entry >= qinfo->dqi_blocks)) { +quota_error (sb,"Block with free entry %u out of range (%u, %u)." , + qinfo->dqi_free_entry,QT_TREEOFF , + qinfo->dqi_blocks); goto out_free; } ret =0 ;
fs/reiserfs/stree.c +1 -1
@@ -1407,7 +1407,7 @@ void reiserfs_delete_solid_item(struct reiserfs_transaction_handle *th,INITIALIZE_PATH (path);int item_len =0 ;int tb_init =0 ; -struct cpu_key cpu_key; +struct cpu_key cpu_key = {};int retval;int quota_cut_bytes =0 ;
fs/romfs/super.c +1 -1
@@ -593,7 +593,7 @@ static void romfs_kill_sb(struct super_block *sb)#ifdef CONFIG_ROMFS_ON_BLOCK if (sb->s_bdev) {sync_blockdev (sb->s_bdev); -blkdev_put (sb->s_bdev, sb); +bdev_release (sb->s_bdev_handle); }#endif }
fs/squashfs/block.c +1 -1
@@ -321,7 +321,7 @@ int squashfs_read_data(struct super_block *sb, u64 index, int length,TRACE ("Block @ 0x%llx, %scompressed size %d\n" , index -2 , compressed ?"" :"un" , length); } -if (length <0 || length > output->length || +if (length <=0 || length > output->length || (index + length) > msblk->bytes_used) { res = -EIO ; goto out;
fs/squashfs/file.c +2 -1
@@ -544,7 +544,8 @@ static void squashfs_readahead(struct readahead_control *ractl)struct squashfs_page_actor *actor;unsigned int nr_pages =0 ;struct page **pages; -int i, file_end =i_size_read (inode) >> msblk->block_log; +int i; +loff_t file_end =i_size_read (inode) >> msblk->block_log;unsigned int max_pages =1UL << shift;readahead_expand (ractl, start, (len | mask) +1 );
fs/squashfs/file_direct.c +3 -3
@@ -26,10 +26,10 @@ int squashfs_readpage_block(struct page *target_page, u64 block, int bsize,struct inode *inode = target_page->mapping->host;struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; -int file_end = (i_size_read (inode) -1 ) >>PAGE_SHIFT ; +loff_t file_end = (i_size_read (inode) -1 ) >>PAGE_SHIFT ;int mask = (1 << (msblk->block_log -PAGE_SHIFT )) -1 ; -int start_index = target_page->index & ~mask; -int end_index = start_index | mask; +loff_t start_index = target_page->index & ~mask; +loff_t end_index = start_index | mask;int i, n, pages, bytes, res = -ENOMEM ;struct page **page;struct squashfs_page_actor *actor;
fs/super.c +9 -6
@@ -1490,14 +1490,16 @@ int setup_bdev_super(struct super_block *sb, int sb_flags, struct fs_context *fc) {blk_mode_t mode =sb_open_mode (sb_flags); +struct bdev_handle *bdev_handle;struct block_device *bdev; - bdev =blkdev_get_by_dev (sb->s_dev, mode, sb, &fs_holder_ops); -if (IS_ERR (bdev)) { + bdev_handle =bdev_open_by_dev (sb->s_dev, mode, sb, &fs_holder_ops); +if (IS_ERR (bdev_handle)) {if (fc)errorf (fc,"%s: Can't open blockdev" , fc->source); -return PTR_ERR (bdev); +return PTR_ERR (bdev_handle); } + bdev = bdev_handle->bdev;/* * This really should be in blkdev_get_by_dev, but right now can't due
@@ -1505,7 +1507,7 @@ int setup_bdev_super(struct super_block *sb, int sb_flags,* writable from userspace even for a read-only block device. */ if ((mode &BLK_OPEN_WRITE ) &&bdev_read_only (bdev)) { -blkdev_put (bdev, sb); +bdev_release (bdev_handle);return -EACCES ; }
@@ -1521,10 +1523,11 @@ int setup_bdev_super(struct super_block *sb, int sb_flags,mutex_unlock (&bdev->bd_fsfreeze_mutex);if (fc)warnf (fc,"%pg: Can't mount, blockdev is frozen" , bdev); -blkdev_put (bdev, sb); +bdev_release (bdev_handle);return -EBUSY ; }spin_lock (&sb_lock); + sb->s_bdev_handle = bdev_handle; sb->s_bdev = bdev; sb->s_bdi =bdi_get (bdev->bd_disk->bdi);if (bdev_stable_writes (bdev))
@@ -1657,7 +1660,7 @@ void kill_block_super(struct super_block *sb)generic_shutdown_super (sb);if (bdev) {sync_blockdev (bdev); -blkdev_put (bdev, sb); +bdev_release (sb->s_bdev_handle); } }
include/linux/cgroup-defs.h +4 -3
@@ -543,6 +543,10 @@ struct cgroup_root {/* Unique id for this hierarchy. */ int hierarchy_id; +/* A list running through the active hierarchies */ +struct list_head root_list; +struct rcu_head rcu;/* Must be near the top */ +/* * The root cgroup. The containing cgroup_root will be destroyed on its * release. cgrp->ancestors[0] will be used overflowing into the
@@ -556,9 +560,6 @@ struct cgroup_root {/* Number of cgroups in the hierarchy, used only for /proc/cgroups */ atomic_t nr_cgrps; -/* A list running through the active hierarchies */ -struct list_head root_list; -/* Hierarchy-specific flags */ unsigned int flags;
include/linux/fs.h +2 -1
@@ -1036,7 +1036,7 @@ struct file_handle {__u32 handle_bytes;int handle_type;/* file identifier */ -unsigned char f_handle[]; + unsigned char f_handle[] __counted_by(handle_bytes); };static inline struct file *get_file (struct file *f)
@@ -1223,6 +1223,7 @@ struct super_block {struct hlist_bl_head s_roots;/* alternate root dentries for NFS */ struct list_head s_mounts;/* list of mounts; _not_ for fs use */ struct block_device *s_bdev; +struct bdev_handle *s_bdev_handle;struct backing_dev_info *s_bdi;struct mtd_info *s_mtd;struct hlist_node s_instances;
include/linux/sockptr.h +25 -0
@@ -50,11 +50,36 @@ static inline int copy_from_sockptr_offset(void *dst, sockptr_t src,return 0 ; } +/* Deprecated. +* This is unsafe, unless caller checked user provided optlen. +* Prefer copy_safe_from_sockptr() instead. +*/ static inline int copy_from_sockptr (void *dst,sockptr_t src,size_t size) {return copy_from_sockptr_offset (dst, src,0 , size); } +/** +* copy_safe_from_sockptr: copy a struct from sockptr +* @dst: Destination address, in kernel space. This buffer must be @ksize +* bytes long. +* @ksize: Size of @dst struct. +* @optval: Source address. (in user or kernel space) +* @optlen: Size of @optval data. +* +* Returns: +* * -EINVAL: @optlen < @ksize +* * -EFAULT: access to userspace failed. +* * 0 : @ksize bytes were copied +*/ +static inline int copy_safe_from_sockptr (void *dst,size_t ksize, +sockptr_t optval,unsigned int optlen) +{ +if (optlen < ksize) +return -EINVAL ; +return copy_from_sockptr (dst, optval, ksize); +} +static inline int copy_to_sockptr_offset (sockptr_t dst,size_t offset,const void *src,size_t size) {
include/linux/sunrpc/svc.h +3 -2
@@ -336,7 +336,6 @@ struct svc_program {const struct svc_version **pg_vers;/* version array */ char * pg_name;/* service name */ char * pg_class;/* class name: services sharing authentication */ -struct svc_stat * pg_stats;/* rpc statistics */ enum svc_auth_status (*pg_authenticate)(struct svc_rqst *rqstp); __be32 (*pg_init_request)(struct svc_rqst *, const struct svc_program *,
@@ -408,7 +407,9 @@ bool svc_rqst_replace_page(struct svc_rqst *rqstp,void svc_rqst_release_pages (struct svc_rqst *rqstp);void svc_rqst_free (struct svc_rqst *);void svc_exit_thread (struct svc_rqst *); -struct svc_serv *svc_create_pooled (struct svc_program *,unsigned int , +struct svc_serv *svc_create_pooled (struct svc_program *prog, +struct svc_stat *stats, +unsigned int bufsize,int (*threadfn)(void *data));int svc_set_num_threads (struct svc_serv *,struct svc_pool *,int );int svc_pool_stats_open (struct svc_serv *serv,struct file *file);
include/uapi/linux/bpf.h +18 -1
@@ -77,12 +77,29 @@ struct bpf_insn {__s32 imm;/* signed immediate constant */ }; -/* Key of an a BPF_MAP_TYPE_LPM_TRIE entry */ +/* Deprecated: use struct bpf_lpm_trie_key_u8 (when the "data" member is needed for +* byte access) or struct bpf_lpm_trie_key_hdr (when using an alternative type for +* the trailing flexible array member) instead. +*/ struct bpf_lpm_trie_key {__u32 prefixlen;/* up to 32 for AF_INET, 128 for AF_INET6 */ __u8 data[0 ];/* Arbitrary size */ }; +/* Header for bpf_lpm_trie_key structs */ +struct bpf_lpm_trie_key_hdr { +__u32 prefixlen; +}; + +/* Key of an a BPF_MAP_TYPE_LPM_TRIE entry, with trailing byte array. */ +struct bpf_lpm_trie_key_u8 { +union { +struct bpf_lpm_trie_key_hdr hdr; +__u32 prefixlen; + }; +__u8 data[];/* Arbitrary size */ +}; +struct bpf_cgroup_storage_key {__u64 cgroup_inode_id;/* cgroup inode id */ __u32 attach_type;/* program attach type (enum bpf_attach_type) */
kernel/bpf/lpm_trie.c +19 -14
@@ -164,13 +164,13 @@ static inline int extract_bit(const u8 *data, size_t index)*/ static size_t longest_prefix_match (const struct lpm_trie *trie,const struct lpm_trie_node *node, -const struct bpf_lpm_trie_key *key) +const struct bpf_lpm_trie_key_u8 *key) {u32 limit =min (node->prefixlen, key->prefixlen);u32 prefixlen =0 , i =0 ;BUILD_BUG_ON (offsetof(struct lpm_trie_node , data) %sizeof (u32)); -BUILD_BUG_ON (offsetof(struct bpf_lpm_trie_key , data) %sizeof (u32)); +BUILD_BUG_ON (offsetof(struct bpf_lpm_trie_key_u8 , data) %sizeof (u32));#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS ) && defined(CONFIG_64BIT )
@@ -229,7 +229,7 @@ static void *trie_lookup_elem(struct bpf_map *map, void *_key) { struct lpm_trie *trie = container_of(map, struct lpm_trie, map);struct lpm_trie_node *node, *found =NULL ; -struct bpf_lpm_trie_key *key = _key; +struct bpf_lpm_trie_key_u8 *key = _key;if (key->prefixlen > trie->max_prefixlen)return NULL ;
@@ -308,8 +308,9 @@ static long trie_update_elem(struct bpf_map *map, { struct lpm_trie *trie = container_of(map, struct lpm_trie, map);struct lpm_trie_node *node, *im_node =NULL , *new_node =NULL ; +struct lpm_trie_node *free_node =NULL ;struct lpm_trie_node __rcu **slot; -struct bpf_lpm_trie_key *key = _key; +struct bpf_lpm_trie_key_u8 *key = _key;unsigned long irq_flags;unsigned int next_bit;size_t matchlen =0 ;
@@ -382,7 +383,7 @@ static long trie_update_elem(struct bpf_map *map, trie->n_entries--;rcu_assign_pointer (*slot, new_node); -kfree_rcu (node, rcu); + free_node = node; goto out; }
@@ -429,6 +430,7 @@ static long trie_update_elem(struct bpf_map *map, }spin_unlock_irqrestore (&trie->lock, irq_flags); +kfree_rcu (free_node, rcu);return ret; }
@@ -437,7 +439,8 @@ static long trie_update_elem(struct bpf_map *map,static long trie_delete_elem (struct bpf_map *map,void *_key) { struct lpm_trie *trie = container_of(map, struct lpm_trie, map); -struct bpf_lpm_trie_key *key = _key; +struct lpm_trie_node *free_node =NULL , *free_parent =NULL ; +struct bpf_lpm_trie_key_u8 *key = _key;struct lpm_trie_node __rcu **trim, **trim2;struct lpm_trie_node *node, *parent;unsigned long irq_flags;
@@ -506,8 +509,8 @@ static long trie_delete_elem(struct bpf_map *map, void *_key)else rcu_assign_pointer ( *trim2,rcu_access_pointer (parent->child[0 ])); -kfree_rcu (parent, rcu); -kfree_rcu (node, rcu); + free_parent = parent; + free_node = node; goto out; }
@@ -521,10 +524,12 @@ static long trie_delete_elem(struct bpf_map *map, void *_key)rcu_assign_pointer (*trim,rcu_access_pointer (node->child[1 ])); else RCU_INIT_POINTER(*trim, NULL); -kfree_rcu (node, rcu); + free_node = node; out:spin_unlock_irqrestore (&trie->lock, irq_flags); +kfree_rcu (free_parent, rcu); +kfree_rcu (free_node, rcu);return ret; }
@@ -536,7 +541,7 @@ static long trie_delete_elem(struct bpf_map *map, void *_key) sizeof(struct lpm_trie_node))#define LPM_VAL_SIZE_MIN 1 -#define LPM_KEY_SIZE (X ) (sizeof(struct bpf_lpm_trie_key) + (X)) +#define LPM_KEY_SIZE (X ) (sizeof(struct bpf_lpm_trie_key_u8) + (X))#define LPM_KEY_SIZE_MAX LPM_KEY_SIZE(LPM_DATA_SIZE_MAX)#define LPM_KEY_SIZE_MIN LPM_KEY_SIZE(LPM_DATA_SIZE_MIN)
@@ -565,7 +570,7 @@ static struct bpf_map *trie_alloc(union bpf_attr *attr)/* copy mandatory map attributes */ bpf_map_init_from_attr (&trie->map, attr); trie->data_size = attr->key_size - - offsetof(struct bpf_lpm_trie_key , data); + offsetof(struct bpf_lpm_trie_key_u8 , data); trie->max_prefixlen = trie->data_size *8 ;spin_lock_init (&trie->lock);
@@ -616,7 +621,7 @@ static int trie_get_next_key(struct bpf_map *map, void *_key, void *_next_key) {struct lpm_trie_node *node, *next_node =NULL , *parent, *search_root; struct lpm_trie *trie = container_of(map, struct lpm_trie, map); -struct bpf_lpm_trie_key *key = _key, *next_key = _next_key; +struct bpf_lpm_trie_key_u8 *key = _key, *next_key = _next_key;struct lpm_trie_node **node_stack =NULL ;int err =0 , stack_ptr =-1 ;unsigned int next_bit;
@@ -703,7 +708,7 @@ static int trie_get_next_key(struct bpf_map *map, void *_key, void *_next_key) } do_copy: next_key->prefixlen = next_node->prefixlen; -memcpy ((void *)next_key + offsetof(struct bpf_lpm_trie_key , data), +memcpy ((void *)next_key + offsetof(struct bpf_lpm_trie_key_u8 , data), next_node->data, trie->data_size); free_stack:kfree (node_stack);
@@ -715,7 +720,7 @@ static int trie_check_btf(const struct bpf_map *map, const struct btf_type *key_type, const struct btf_type *value_type) { - /* Keys must have struct bpf_lpm_trie_key embedded. */ + /* Keys must have struct bpf_lpm_trie_key_u8 embedded. */ return BTF_INFO_KIND(key_type->info) != BTF_KIND_STRUCT ? -EINVAL : 0; }
kernel/cgroup/cgroup-internal.h +2 -1
@@ -170,7 +170,8 @@ extern struct list_head cgroup_roots;/* iterate across the hierarchies */ #define for_each_root (root) \ - list_for_each_entry((root), &cgroup_roots, root_list) + list_for_each_entry_rcu((root), &cgroup_roots, root_list, \ + lockdep_is_held(&cgroup_mutex))/** * for_each_subsys - iterate all enabled cgroup subsystems
kernel/cgroup/cgroup.c +16 -7
@@ -1313,7 +1313,7 @@ static void cgroup_exit_root_id(struct cgroup_root *root)void cgroup_free_root (struct cgroup_root *root) { -kfree (root); +kfree_rcu (root, rcu); }static void cgroup_destroy_root (struct cgroup_root *root)
@@ -1346,7 +1346,7 @@ static void cgroup_destroy_root(struct cgroup_root *root)spin_unlock_irq (&css_set_lock);if (!list_empty (&root->root_list)) { -list_del (&root->root_list); +list_del_rcu (&root->root_list); cgroup_root_count--; }
@@ -1386,7 +1386,15 @@ static inline struct cgroup *__cset_cgroup_from_root(struct css_set *cset, } } -BUG_ON (!res_cgroup); +/* +* If cgroup_mutex is not held, the cgrp_cset_link will be freed +* before we remove the cgroup root from the root_list. Consequently, +* when accessing a cgroup root, the cset_link may have already been +* freed, resulting in a NULL res_cgroup. However, by holding the +* cgroup_mutex, we ensure that res_cgroup can't be NULL. +* If we don't hold cgroup_mutex in the caller, we must do the NULL +* check. +*/ return res_cgroup; }
@@ -1445,7 +1453,6 @@ static struct cgroup *current_cgns_cgroup_dfl(void)static struct cgroup *cset_cgroup_from_root (struct css_set *cset,struct cgroup_root *root) { -lockdep_assert_held (&cgroup_mutex);lockdep_assert_held (&css_set_lock);return __cset_cgroup_from_root (cset, root);
@@ -1453,7 +1460,9 @@ static struct cgroup *cset_cgroup_from_root(struct css_set *cset,/* * Return the cgroup for "task" from the given hierarchy. Must be -* called with cgroup_mutex and css_set_lock held. +* called with css_set_lock held to prevent task's groups from being modified. +* Must be called with either cgroup_mutex or rcu read lock to prevent the +* cgroup root from being destroyed. */ struct cgroup *task_cgroup_from_root (struct task_struct *task,struct cgroup_root *root)
@@ -2014,7 +2023,7 @@ void init_cgroup_root(struct cgroup_fs_context *ctx)struct cgroup_root *root = ctx->root;struct cgroup *cgrp = &root->cgrp; -INIT_LIST_HEAD (&root->root_list); +INIT_LIST_HEAD_RCU (&root->root_list);atomic_set (&root->nr_cgrps,1 ); cgrp->root = root;init_cgroup_housekeeping (cgrp);
@@ -2097,7 +2106,7 @@ int cgroup_setup_root(struct cgroup_root *root, u16 ss_mask)* care of subsystems' refcounts, which are explicitly dropped in * the failure exit path. */ -list_add (&root->root_list, &cgroup_roots); +list_add_rcu (&root->root_list, &cgroup_roots); cgroup_root_count++;/*
kernel/irq/cpuhotplug.c +24 -3
@@ -130,6 +130,22 @@ static bool migrate_one_irq(struct irq_desc *desc)* CPU. */ err =irq_do_set_affinity (d, affinity, false); + +/* +* If there are online CPUs in the affinity mask, but they have no +* vectors left to make the migration work, try to break the +* affinity by migrating to any online CPU. +*/ +if (err == -ENOSPC && !irqd_affinity_is_managed (d) && affinity != cpu_online_mask) { +pr_debug ("IRQ%u: set affinity failed for %*pbl, re-try with online CPUs\n" , + d->irq,cpumask_pr_args (affinity)); + + affinity = cpu_online_mask; + brokeaff = true; + + err =irq_do_set_affinity (d, affinity, false); + } +if (err) {pr_warn_ratelimited ("IRQ%u: set affinity failed(%d).\n" , d->irq, err);
@@ -195,10 +211,15 @@ static void irq_restore_affinity_of_irq(struct irq_desc *desc, unsigned int cpu) !irq_data_get_irq_chip(data) || !cpumask_test_cpu(cpu, affinity))return ; -if (irqd_is_managed_and_shutdown (data)) { -irq_startup (desc,IRQ_RESEND ,IRQ_START_COND ); +/* +* Don't restore suspended interrupts here when a system comes back +* from S3. They are reenabled via resume_device_irqs(). +*/ +if (desc->istate &IRQS_SUSPENDED )return ; - } + +if (irqd_is_managed_and_shutdown (data)) +irq_startup (desc,IRQ_RESEND ,IRQ_START_COND );/* * If the interrupt can only be directed to a single target
kernel/irq/manage.c +8 -4
@@ -796,10 +796,14 @@ void __enable_irq(struct irq_desc *desc)irq_settings_set_noprobe (desc);/* * Call irq_startup() not irq_enable() here because the -* interrupt might be marked NOAUTOEN. So irq_startup() -* needs to be invoked when it gets enabled the first -* time. If it was already started up, then irq_startup() -* will invoke irq_enable() under the hood. +* interrupt might be marked NOAUTOEN so irq_startup() +* needs to be invoked when it gets enabled the first time. +* This is also required when __enable_irq() is invoked for +* a managed and shutdown interrupt from the S3 resume +* path. +* +* If it was already started up, then irq_startup() will +* invoke irq_enable() under the hood. */ irq_startup (desc,IRQ_RESEND ,IRQ_START_FORCE );break ;
mm/debug_vm_pgtable.c +5 -26
@@ -39,22 +39,7 @@* Please refer Documentation/mm/arch_pgtable_helpers.rst for the semantics * expectations that are being validated here. All future changes in here * or the documentation need to be in sync. -* -* On s390 platform, the lower 4 bits are used to identify given page table -* entry type. But these bits might affect the ability to clear entries with -* pxx_clear() because of how dynamic page table folding works on s390. So -* while loading up the entries do not change the lower 4 bits. It does not -* have affect any other platform. Also avoid the 62nd bit on ppc64 that is -* used to mark a pte entry. */ -#define S390_SKIP_MASK GENMASK(3, 0) -#if __BITS_PER_LONG ==64 -#define PPC64_SKIP_MASK GENMASK(62, 62) -#else -#define PPC64_SKIP_MASK 0x0 -#endif -#define ARCH_SKIP_MASK (S390_SKIP_MASK | PPC64_SKIP_MASK) -#define RANDOM_ORVALUE (GENMASK(BITS_PER_LONG - 1, 0) & ~ARCH_SKIP_MASK)#define RANDOM_NZVALUE GENMASK(7, 0)struct pgtable_debug_args {
@@ -510,8 +495,7 @@ static void __init pud_clear_tests(struct pgtable_debug_args *args)return ;pr_debug ("Validating PUD clear\n" ); - pud =__pud (pud_val (pud) |RANDOM_ORVALUE ); -WRITE_ONCE (*args->pudp, pud); +WARN_ON (pud_none (pud));pud_clear (args->pudp); pud =READ_ONCE (*args->pudp);WARN_ON (!pud_none (pud));
@@ -547,8 +531,7 @@ static void __init p4d_clear_tests(struct pgtable_debug_args *args)return ;pr_debug ("Validating P4D clear\n" ); - p4d =__p4d (p4d_val (p4d) |RANDOM_ORVALUE ); -WRITE_ONCE (*args->p4dp, p4d); +WARN_ON (p4d_none (p4d));p4d_clear (args->p4dp); p4d =READ_ONCE (*args->p4dp);WARN_ON (!p4d_none (p4d));
@@ -581,8 +564,7 @@ static void __init pgd_clear_tests(struct pgtable_debug_args *args)return ;pr_debug ("Validating PGD clear\n" ); - pgd =__pgd (pgd_val (pgd) |RANDOM_ORVALUE ); -WRITE_ONCE (*args->pgdp, pgd); +WARN_ON (pgd_none (pgd));pgd_clear (args->pgdp); pgd =READ_ONCE (*args->pgdp);WARN_ON (!pgd_none (pgd));
@@ -633,10 +615,8 @@ static void __init pte_clear_tests(struct pgtable_debug_args *args)if (WARN_ON (!args->ptep))return ; -#ifndef CONFIG_RISCV - pte =__pte (pte_val (pte) |RANDOM_ORVALUE ); -#endif set_pte_at (args->mm, args->vaddr, args->ptep, pte); +WARN_ON (pte_none (pte));flush_dcache_page (page);barrier ();ptep_clear (args->mm, args->vaddr, args->ptep);
@@ -649,8 +629,7 @@ static void __init pmd_clear_tests(struct pgtable_debug_args *args)pmd_t pmd =READ_ONCE (*args->pmdp);pr_debug ("Validating PMD clear\n" ); - pmd =__pmd (pmd_val (pmd) |RANDOM_ORVALUE ); -WRITE_ONCE (*args->pmdp, pmd); +WARN_ON (pmd_none (pmd));pmd_clear (args->pmdp); pmd =READ_ONCE (*args->pmdp);WARN_ON (!pmd_none (pmd));
mm/gup.c +129 -122
365 lines not on this page · raw message
mm/huge_memory.c +3 -3
@@ -1056,7 +1056,7 @@ struct page *follow_devmap_pmd(struct vm_area_struct *vma, unsigned long addr,if (!*pgmap)return ERR_PTR (-EFAULT ); page =pfn_to_page (pfn); - ret =try_grab_page (page, flags); + ret =try_grab_folio (page_folio (page),1 , flags);if (ret) page =ERR_PTR (ret);
@@ -1214,7 +1214,7 @@ struct page *follow_devmap_pud(struct vm_area_struct *vma, unsigned long addr,return ERR_PTR (-EFAULT ); page =pfn_to_page (pfn); - ret =try_grab_page (page, flags); + ret =try_grab_folio (page_folio (page),1 , flags);if (ret) page =ERR_PTR (ret);
@@ -1475,7 +1475,7 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,VM_BUG_ON_PAGE ((flags &FOLL_PIN ) &&PageAnon (page) && !PageAnonExclusive (page), page); - ret =try_grab_page (page, flags); + ret =try_grab_folio (page_folio (page),1 , flags);if (ret)return ERR_PTR (ret);
mm/hugetlb.c +1 -1
@@ -6532,7 +6532,7 @@ struct page *hugetlb_follow_page_mask(struct vm_area_struct *vma,* try_grab_page() should always be able to get the page here, * because we hold the ptl lock and have verified pte_present(). */ - ret =try_grab_page (page, flags); + ret =try_grab_folio (page_folio (page),1 , flags);if (WARN_ON_ONCE (ret)) { page =ERR_PTR (ret);
mm/internal.h +2 -2
@@ -938,8 +938,8 @@ int migrate_device_coherent_page(struct page *page);/* * mm/gup.c */ -struct folio *try_grab_folio (struct page *page,int refs,unsigned int flags); -int __must_check try_grab_page (struct page *page,unsigned int flags); +int __must_check try_grab_folio (struct folio *folio,int refs, +unsigned int flags);/* * mm/huge_memory.c
mm/page_table_check.c +30 -0
@@ -7,6 +7,8 @@#include <linux/kstrtox.h> #include <linux/mm.h> #include <linux/page_table_check.h> +#include <linux/swap.h> +#include <linux/swapops.h> #undef pr_fmt#define pr_fmt (fmt) "page_table_check: " fmt
@@ -191,6 +193,22 @@ void __page_table_check_pud_clear(struct mm_struct *mm, pud_t pud) }EXPORT_SYMBOL (__page_table_check_pud_clear); +/* Whether the swap entry cached writable information */ +static inline bool swap_cached_writable (swp_entry_t entry) +{ +return is_writable_device_exclusive_entry (entry) || +is_writable_device_private_entry (entry) || +is_writable_migration_entry (entry); +} + +static inline void page_table_check_pte_flags (pte_t pte) +{ +if (pte_present (pte) &&pte_uffd_wp (pte)) +WARN_ON_ONCE (pte_write (pte)); +else if (is_swap_pte (pte) &&pte_swp_uffd_wp (pte)) +WARN_ON_ONCE (swap_cached_writable (pte_to_swp_entry (pte))); +} +void __page_table_check_ptes_set (struct mm_struct *mm,pte_t *ptep,pte_t pte,unsigned int nr) {
@@ -199,6 +217,8 @@ void __page_table_check_ptes_set(struct mm_struct *mm, pte_t *ptep, pte_t pte,if (&init_mm == mm)return ; +page_table_check_pte_flags (pte); +for (i =0 ; i < nr; i++)__page_table_check_pte_clear (mm,ptep_get (ptep + i));if (pte_user_accessible_page (pte))
@@ -206,11 +226,21 @@ void __page_table_check_ptes_set(struct mm_struct *mm, pte_t *ptep, pte_t pte, }EXPORT_SYMBOL (__page_table_check_ptes_set); +static inline void page_table_check_pmd_flags (pmd_t pmd) +{ +if (pmd_present (pmd) &&pmd_uffd_wp (pmd)) +WARN_ON_ONCE (pmd_write (pmd)); +else if (is_swap_pmd (pmd) &&pmd_swp_uffd_wp (pmd)) +WARN_ON_ONCE (swap_cached_writable (pmd_to_swp_entry (pmd))); +} +void __page_table_check_pmd_set (struct mm_struct *mm,pmd_t *pmdp,pmd_t pmd) {if (&init_mm == mm)return ; +page_table_check_pmd_flags (pmd); +__page_table_check_pmd_clear (mm, *pmdp);
Lines of this file are not shown. View the raw message.
tools/testing/selftests/bpf/progs/map_ptr_kern.c +1 -1
Lines of this file are not shown. View the raw message.
tools/testing/selftests/bpf/test_lpm_map.c +9 -9
Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Part of the diff is not shown here. View the raw message.