Merge branch 'android13-5.15' into android13-5.15-lts

Sync up with android13-5.15 for the following commits:

*   5476e160a6 Merge "Merge tag 'android13-5.15.94_r00' into android13-5.15" into android13-5.15
|\
| * 5155624549 Merge tag 'android13-5.15.94_r00' into android13-5.15
* | e5862f1a40 UPSTREAM: wifi: nl80211: fix puncturing bitmap policy
|/
* f8c9753a12 UPSTREAM: hwrng: virtio - add an internal buffer
* 1dddc1992e ANDROID: GKI: Update abi_gki_aarch64_qcom
* 092199e995 BACKPORT: wifi: nl80211: Allow authentication frames and set keys on NAN interface
* 05164a8564 UPSTREAM: wifi: cfg80211: Allow action frames to be transmitted with link BSS in MLD
* 6bab8a4002 BACKPORT: wifi: cfg80211: include puncturing bitmap in channel switch events
* e8a4772f4d BACKPORT: wifi: nl80211: validate and configure puncturing bitmap
* b099f1eb0b UPSTREAM: regmap: Don't warn about cache only mode for devices with no cache
* b3ebd7ca3b ANDROID: dma-buf: system_heap: kmap_local_page instead of kmap_atomic
* 16e9875abd ANDROID: GKI: update xiaomi symbol list
* cf18e5eb5e UPSTREAM: ext4: fix another off-by-one fsmap error on 1k block filesystems
* 090c1ebf8d UPSTREAM: dm verity: stop using WQ_UNBOUND for verify_wq
* 7f356bba02 BACKPORT: dm verity: enable WQ_HIGHPRI on verify_wq
* 4017ffbb86 UPSTREAM: dm verity: remove WQ_CPU_INTENSIVE flag since using WQ_UNBOUND
* a6c4727f6a UPSTREAM: loop: Fix use-after-free issues
* 24c1fcb787 ANDROID: GKI: Update symbol list for mtk
* 6c60fdbac2 UPSTREAM: ext4: block range must be validated before use in ext4_mb_clear_bb()
* 53ce0eef46 UPSTREAM: ext4: add strict range checks while freeing blocks
* 20389d86cb UPSTREAM: ext4: add ext4_sb_block_valid() refactored out of ext4_inode_block_valid()
* 60c24f4d15 UPSTREAM: ext4: refactor ext4_free_blocks() to pull out ext4_mb_clear_bb()
* 7ba7908a8d ANDROID: mm: handle SPF using a copy of the original vma
* 521f3bc70d ANDROID: mm: fix UAF in SPF
* e09118b90b ANDROID: GKI: Update symbol list for mtk
* 0659efffd9 UPSTREAM: arm64: efi: Make efi_rt_lock a raw_spinlock
* 6b908238a8 UPSTREAM: wifi: cfg80211: Set SSID if it is not already set
* 554a967167 Revert "Revert "ANDROID: usb: dwc3: gadget: don't cancel the started requests""
* eef9e1295b UPSTREAM: rtmutex: Ensure that the top waiter is always woken up
* cc0db0b28c UPSTREAM: cgroup/cpuset: Don't filter offline CPUs in cpuset_cpus_allowed() for top cpuset tasks
* 3c4f884306 UPSTREAM: ext4: refuse to create ea block when umounted
* 0473082f7a UPSTREAM: ext4: optimize ea_inode block expansion
* bf0b8e8181 UPSTREAM: ext4: allocate extended attribute value in vmalloc area
* 79bd2581b8 ANDROID: ABI: Update the GKI symbol list and ABI XML
* cfe5bd7f01 ANDROID: abi_gki_aarch64_qcom: Update symbol list
* f3091267ac ANDROID: GKI: update xiaomi symbol list
* fb1db47637 UPSTREAM: Partially revert "perf/arm-cmn: Optimise DTC counter accesses"
* 1f12217e5d UPSTREAM: usb: dwc3: gadget: Ignore End Transfer delay on teardown
* fc41b9e122 UPSTREAM: elfcore: Add a cprm parameter to elf_core_extra_{phdrs,data_size}
* ee863e2109 UPSTREAM: arm64: mte: Fix double-freeing of the temporary tag storage during coredump
* 7dc85abaac UPSTREAM: wifi: nl80211: Add checks for nla_nest_start() in nl80211_send_iface()
* 8b1316dd5b UPSTREAM: mm/page_exit: fix kernel doc warning in page_ext_put()
* 37fbaa232d UPSTREAM: f2fs: fix gc mode when gc_urgent_high_remaining is 1
* ad8cc978cc BACKPORT: mm: multi-gen LRU: move lru_gen_add_mm() out of IRQ-off region
* 73d24f728f UPSTREAM: KVM: arm64: Use correct accessor to parse stage-1 PTEs
* 2f6641fde7 UPSTREAM: wifi: fix multi-link element subelement iteration
* 0cc04953f0 UPSTREAM: perf/arm-cmn: Add more bits to child node address offset field
* a481cc4587 UPSTREAM: perf/arm-cmn: Update watchpoint format
* 668c43092b UPSTREAM: perf/arm-cmn: Hide XP PUB events for CMN-600
* 5761541a4e BACKPORT: wifi: cfg80211: move puncturing bitmap validation from mac80211
* 267de69e07 UPSTREAM: wifi: nl80211: add MLO_LINK_ID to CMD_STOP_AP event
* 83e77c3183 BACKPORT: cfg80211: Update Transition Disable policy during port authorization
* f4559cb666 ANDROID: ABI: Update db845c symbol list on ufshcd
* bef41f506f ANDROID: usb: gadget: f_accessory: update to usb_gstrings_attach
* 0fd1c2a78d UPSTREAM: usb: gadget: composite: Draw 100mA current if not configured
* a223191ed9 UPSTREAM: usb: dwc3: gadget: Change condition for processing suspend event
* 91c677412c UPSTREAM: net/sched: tcindex: update imperfect hash filters respecting rcu
* 6ca9fd3a0c BACKPORT: FROMGIT: scsi: ufs: core: Add hibernation callbacks
* 35d26a7736 ANDROID: ABI: Update unisoc thermal symbol list
* 683fe954dc ANDROID: thermal: Add a vendor hook for thermal throttle update
* e013dc7081 ANDROID: GKI: Add symbol list for Lenovo
* 6a7aa09013 ANDROID: Enable percpu high priority kthreads for erofs
* 40a9ba963b UPSTREAM: erofs: fix an error code in z_erofs_init_zip_subsystem()
* 7dc188b222 BACKPORT: erofs: add per-cpu threads for decompression as an option
* 4fd62a87f5 ANDROID: ABI: Update oplus symbol list
* 05b5ff11ad ANDROID: vendor_hooks: Add hooks for mutex and rwsem optimistic spin
* 9eec95bb4b UPSTREAM: io_uring: ensure that io_init_req() passes in the right issue_flags
* c112dc5771 ANDROID: Update the GKI symbol list and ABI XML
* bdf1c2ccdf UPSTREAM: io_uring: add missing lock in io_get_file_fixed
* 3352886cae ANDROID: gki_config: enable CONFIG_IIO_TRIGGERED_BUFFER
* e21e3d108b ANDROID: GKI: VIVO: Add a symbol to symbol list
* 5239ef3d19 UPSTREAM: drivers/thermal/cpufreq_cooling: Use private callback ops for each cooling device
* 287c9980a0 UPSTREAM: scsi: scsi_debug: Fix possible UAF in sdebug_add_host_helper()
* 6db5181a3f UPSTREAM: io_uring/rw: remove leftover debug statement
* 4390be5c79 UPSTREAM: io_uring/rw: ensure kiocb_end_write() is always called
* 6b3d1f961d UPSTREAM: io_uring: fix double poll leak on repolling
* 3749f8d826 UPSTREAM: io_uring: Clean up a false-positive warning from GCC 9.3.0
* 0da7ee3fbe UPSTREAM: io_uring/net: fix fast_iov assignment in io_setup_async_msg()
* 3a4f67f903 UPSTREAM: io_uring: io_kiocb_update_pos() should not touch file for non -1 offset
* 3c83e0a95a UPSTREAM: io_uring/rw: defer fsnotify calls to task context
* 630c372219 UPSTREAM: io_uring: do not recalculate ppos unnecessarily
* 47179f7dd8 UPSTREAM: io_uring: update kiocb->ki_pos at execution time
* b0b3d93abc UPSTREAM: io_uring: remove duplicated calls to io_kiocb_ppos
* 7b865f60c7 UPSTREAM: io_uring: ensure that cached task references are always put on exit
* c72cbb2252 UPSTREAM: io_uring: fix async accept on O_NONBLOCK sockets
* 88be697dc0 UPSTREAM: io_uring: allow re-poll if we made progress
* 393d994594 UPSTREAM: io_uring: support MSG_WAITALL for IORING_OP_SEND(MSG)
* 8f3a4070fd UPSTREAM: io_uring: add flag for disabling provided buffer recycling
* b0b6bfe443 UPSTREAM: io_uring: ensure recv and recvmsg handle MSG_WAITALL correctly
* 40520bb96c UPSTREAM: io_uring: improve send/recv error handling
* 6c0dd68dbe UPSTREAM: io_uring: pass in EPOLL_URING_WAKE for eventfd signaling and wakeups
* ab6956ac6b UPSTREAM: eventfd: provide a eventfd_signal_mask() helper
* b4ab4ac900 UPSTREAM: eventpoll: add EPOLL_URING_WAKE poll wakeup flag
* 2373a0c72f UPSTREAM: io_uring: don't gate task_work run on TIF_NOTIFY_SIGNAL
* b579578d93 UPSTREAM: io_uring/io-wq: only free worker if it was allocated for creation
* 19758f54f7 UPSTREAM: io_uring/io-wq: free worker if task_work creation is canceled
* 65e1f2ef67 UPSTREAM: io_uring: lock overflowing for IOPOLL
* 198e5002e2 UPSTREAM: io_uring: Fix unsigned 'res' comparison with zero in io_fixup_rw_res()
* 5af453ff63 UPSTREAM: io_uring: fix CQ waiting timeout handling
* e6f9c1b71a UPSTREAM: io_uring: check for valid register opcode earlier
* dcc1ea1639 UPSTREAM: io_uring: Fix a null-ptr-deref in io_tctx_exit_cb()
* 3a1c153b96 UPSTREAM: io_uring: move to separate directory
* c0dee08111 UPSTREAM: io_uring/poll: fix poll_refs race with cancelation
* 5a5dcf5c1d UPSTREAM: io_uring: make poll refs more robust
* 30909f865b UPSTREAM: io_uring: cmpxchg for poll arm refs release
* 242ed49852 UPSTREAM: io_uring: fix tw losing poll events
* 7e603b2079 UPSTREAM: io_uring: update res mask in io_poll_check_events
* fab4d02938 UPSTREAM: wifi: cfg80211: Extend cfg80211_update_owe_info_event() for MLD AP
* 048ad5d375 UPSTREAM: wifi: cfg80211: Extend cfg80211_new_sta() for MLD AP
* 9216110fdf UPSTREAM: wifi: cfg80211: Authentication offload to user space for MLO connection in STA mode
* 272c5a9d37 UPSTREAM: wifi: cfg80211: trace: remove MAC_PR_{FMT,ARG}
* 99da8df376 UPSTREAM: KVM: VMX: Execute IBPB on emulated VM-exit when guest has IBRS
* 16bb33d7ef ANDROID: ABI: Update allowed list for QCOM
* 3383d21e9e UPSTREAM: wifi: cfg80211: Support 32 bytes KCK key in GTK rekey offload
* 26bac3f093 ANDROID: MGLRU: Don't skip anon reclaim if swap low
* 151bc21658 ANDROID: incremental fs: Move throttling to outside page lock
* 3ab6fda925 ANDROID: incremental fs: Fix race between truncate and write last block
* aba5f5754b ANDROID: fuse-bpf: Do not change bpf program in lookups
* dd72bb259f UPSTREAM: usb: gadget: u_serial: Add null pointer check in gserial_resume
* a2ee0d8df3 UPSTREAM: binder: Gracefully handle BINDER_TYPE_FDA objects with num_fds=0
* 9cdb4e5812 UPSTREAM: binder: Address corner cases in deferred copy and fixup
* 884fec935c UPSTREAM: binder: fix pointer cast warning
* 0502554803 UPSTREAM: binder: defer copies of pre-patched txn data
* a9afae9aa4 UPSTREAM: binder: read pre-translated fds from sender buffer
* 7887b13e6b UPSTREAM: net_sched: reject TCF_EM_SIMPLE case for complex ematch module
* 89eccb8495 UPSTREAM: ext4: add inode table check in __ext4_get_inode_loc to aovid possible infinite loop
* fda78dabca Revert "ANDROID: GKI: Add vendor hook to binder transaction"
* c404b74d5f ANDROID: GKI: Update the ABI xml representation for fuse-bpf
* 7a1cca7dbd ANDROID: fuse-bpf: Add /sys/fs flags for fuse-bpf version
* f5f4199c10 ANDROID: fuse-bpf v1.1
* bff9debefd ANDROID: GKI: update xiaomi symbol list
* 5a6502af11 ANDROID: psi: Add vendor hooks for PSI tracing
* af8dfb011f FROMLIST: input: Add KEY_CAMERA_FOCUS event in HID
* 79b3761c89 BACKPORT: sched/core: Fix use-after-free bug in dup_user_cpus_ptr()
* a838fd5d08 Revert "FROMGIT: sched: Add __releases annotations to affine_move_task()"
* 5767bdca07 Revert "BACKPORT: FROMGIT: sched: Introduce affinity_context"
* 158d54a8a8 Revert "BACKPORT: FROMGIT: sched: Always preserve the user requested cpumask"
* 92bd55bc52 Revert "FROMLIST: sched: Fix use-after-free bug in dup_user_cpus_ptr()"
* bd82038474 Revert "BACKPORT: FROMGIT: sched: Enforce user requested affinity"
* 0f54a1c923 Revert "FROMGIT: sched: Always clear user_cpus_ptr in do_set_cpus_allowed()"
* 97c7d8de1d Revert "ANDROID: sched: Keep sched_class::set_cpus_allowed stable"
* 4ef9aa1b49 Revert "ANDROID: sched: Move scratch_mask to a percpu variable"
* aa27279666 BACKPORT: of: reserved_mem: Have kmemleak ignore dynamically allocated reserved mem
* 20c1f0a6d2 Revert "BACKPORT: FROMGIT: mm/cma.c: make kmemleak aware of all CMA regions"
* 5862eafd8e Revert "FROMGIT: mm/cma.c: delete kmemleak objects when freeing CMA areas to buddy at boot"
* 5c6418ddee Revert "UPSTREAM: mm: kmemleak: alloc gray object for reserved region with direct map"
* 45a51d2eb8 ANDROID: GKI: Update symbol list for Amlogic
* d41e54aefb ANDROID: GKI: Add symbol list for ZEKU
* 32d4e80df4 ANDROID: dm-bow: Add ABI documentation
* 88e27b17aa ANDROID: dm-bow: Fix 5.15 compatibility issue
* 63a1e5f1d0 Revert "ANDROID: dm-bow: remove dm-bow"
* d07a013cd0 ANDROID: vendor_hook: fix the error record of rwsem
* 5fcf93b316 ANDROID: ABI: Update allowed list for QCOM
* 16e7178e58 ANDROID: GKI: Update abi_gki_aarch64_qcom symbols
* 4ef0a7dff1 ANDROID: crypto: testmgr - add back deleted hctr2 test vectors
* 2cde0330aa ANDROID: abi_gki_aarch64_qcom: Add rpmsg_rx_done and zap_vma_ptes
* 810133cb61 ANDROID: cpuidle-psci: Fix suspicious RCU usage
* 6f810b08ef FROMGIT: usb: gadget: configfs: Restrict symlink creation is UDC already binded
* 9dff37ba7b ANDROID: Update symbol list for sunxi
* 18eaf71786 FROMGIT: scsi: ufs: Try harder to change the power mode
* cfc314cd6f UPSTREAM: scsi: ufs: Reduce the START STOP UNIT timeout
* 6a9193a0ff UPSTREAM: 9p/fd: fix issue of list_del corruption in p9_fd_cancel()
* b4c3ac4720 UPSTREAM: fs: do not update freeing inode i_io_list
* b607fae900 UPSTREAM: f2fs: fix to invalidate dcc->f2fs_issue_discard in error path
* 0b34c91b83 FROMGIT: wifi: cfg80211: Fix extended KCK key length check in nl80211_set_rekey_data()
* f719d33f11 UPSTREAM: iommu/iova: Fix alloc iova overflows issue
* 43c604d36e UPSTREAM: iommu: Avoid races around device probe
* 613751d732 ANDROID: GKI: Update abi_gki_aarch64_pasa
* 2f7c6eb587 ANDROID: softirq: Refine RT defer softirq
* 286300ece4 UPSTREAM: wifi: wilc1000: validate number of channels
* 7594f016ed UPSTREAM: wifi: wilc1000: validate pairwise and authentication suite offsets
* d9a54ce812 UPSTREAM: wifi: wilc1000: validate length of IEEE80211_P2P_ATTR_OPER_CHANNEL attribute
* 0be0985947 UPSTREAM: media: dvb-core: Fix UAF due to refcount races at releasing
* e5905d8ab3 ANDROID: Update the GKI symbol list and ABI XML
* 984241bdc0 UPSTREAM: efi: rt-wrapper: Add missing include
* ec6fe82350 UPSTREAM: arm64: efi: Execute runtime services from a dedicated stack
* 003dacfcee UPSTREAM: KVM: x86/mmu: Fix race condition in direct_page_fault
* 19987d1e7f UPSTREAM: usb: gadget: uvc: Rename bmInterfaceFlags -> bmInterlaceFlags
* 6d2ec81c11 ANDROID: GKI: KASAN: disable INLINE
* ae0a1eb830 ANDROID: GKI: Update symbol list for mtk
* 9a8dcea6ab ANDROID: usb: f_accessory: Check buffer size when initialised via composite
* 2a298e88eb UPSTREAM: drm/shmem-helper: Avoid vm_open error paths
* 2c76d2b9c5 UPSTREAM: proc: avoid integer type confusion in get_proc_long
* cc6c5c7fa2 UPSTREAM: ALSA: pcm: Move rwsem lock inside snd_ctl_elem_read to prevent UAF
* 0861407d6e UPSTREAM: proc: proc_skip_spaces() shouldn't think it is working on C strings
* 3cf30601b0 UPSTREAM: usb: gadget: f_hid: fix f_hidg lifetime vs cdev
* 8864b0342f UPSTREAM: nfp: fix use-after-free in area_cache_get()
* 9563d28619 FROMGIT: scsi: ufs: Modify Tactive time setting conditions
* afe869b80a ANDROID: gki_defconfig: disable various x86 and hw flags
* 4dc28fe928 UPSTREAM: usb: gadget: f_fs: Fix unbalanced spinlock in __ffs_ep0_queue_wait

.xml file is updated due to new symbols being now tracked:

76 function symbol(s) added
  'u64 __blkg_prfill_rwstat(struct seq_file*, struct blkg_policy_data*, const struct blkg_rwstat_sample*)'
  'u64 __blkg_prfill_u64(struct seq_file*, struct blkg_policy_data*, u64)'
  'void __free_iova(struct iova_domain*, struct iova*)'
  'int __traceiter_android_vh_modify_thermal_throttle_update(void*, struct thermal_zone_device*, bool*)'
  'int __traceiter_android_vh_mpam_set(void*, struct task_struct*, struct task_struct*)'
  'int __traceiter_android_vh_mutex_can_spin_on_owner(void*, struct mutex*, int*)'
  'int __traceiter_android_vh_mutex_opt_spin_finish(void*, struct mutex*, bool)'
  'int __traceiter_android_vh_mutex_opt_spin_start(void*, struct mutex*, bool*, int*)'
  'int __traceiter_android_vh_psi_group(void*, struct psi_group*)'
  'int __traceiter_android_vh_rwsem_can_spin_on_owner(void*, struct rw_semaphore*, bool*)'
  'int __traceiter_android_vh_rwsem_opt_spin_finish(void*, struct rw_semaphore*, bool)'
  'int __traceiter_android_vh_rwsem_opt_spin_start(void*, struct rw_semaphore*, bool*, int*, bool)'
  'int __traceiter_wbc_writepage(void*, struct writeback_control*, struct backing_dev_info*)'
  'struct iova* alloc_iova(struct iova_domain*, unsigned long int, unsigned long int, bool)'
  'const char* bdi_dev_name(struct backing_dev_info*)'
  'void blkcg_print_blkgs(struct seq_file*, struct blkcg*, u64(*)(struct seq_file*, struct blkg_policy_data*, int), const struct blkcg_policy*, int, bool)'
  'void blkg_conf_finish(struct blkg_conf_ctx*)'
  'int blkg_conf_prep(struct blkcg*, const struct blkcg_policy*, char*, struct blkg_conf_ctx*)'
  'u64 blkg_prfill_rwstat(struct seq_file*, struct blkg_policy_data*, int)'
  'void blkg_rwstat_exit(struct blkg_rwstat*)'
  'int blkg_rwstat_init(struct blkg_rwstat*, gfp_t)'
  'void blkg_rwstat_recursive_sum(struct blkcg_gq*, struct blkcg_policy*, int, struct blkg_rwstat_sample*)'
  'u64 clockevent_delta2ns(unsigned long int, struct clock_event_device*)'
  'void clockevents_register_device(struct clock_event_device*)'
  'int crypto_authenc_extractkeys(struct crypto_authenc_keys*, const u8*, unsigned int)'
  'struct dentry* d_alloc_name(struct dentry*, const char*)'
  'void* devm_pci_remap_cfg_resource(struct device*, struct resource*)'
  'void* devm_pci_remap_cfgspace(struct device*, resource_size_t, resource_size_t)'
  'void devm_release_resource(struct device*, struct resource*)'
  'int divider_determine_rate(struct clk_hw*, struct clk_rate_request*, const struct clk_div_table*, u8, unsigned long int)'
  'struct iova* find_iova(struct iova_domain*, unsigned long int)'
  'struct file_system_type* get_fs_type(const char*)'
  'unsigned int get_next_ino()'
  'int get_tree_single(struct fs_context*, int(*)(struct super_block*, struct fs_context*))'
  'struct iio_channel* iio_channel_get_all(struct device*)'
  'void iio_channel_release_all(struct iio_channel*)'
  'struct iio_buffer* iio_kfifo_allocate()'
  'ssize_t iio_read_const_attr(struct device*, struct device_attribute*, char*)'
  'irqreturn_t iio_trigger_generic_data_rdy_poll(int, void*)'
  'void iio_triggered_buffer_cleanup(struct iio_dev*)'
  'int iio_triggered_buffer_setup_ext(struct iio_dev*, irqreturn_t(*)(int, void*), irqreturn_t(*)(int, void*), const struct iio_buffer_setup_ops*, const struct attribute**)'
  'int iio_update_buffers(struct iio_dev*, struct iio_buffer*, struct iio_buffer*)'
  'bool iio_validate_scan_mask_onehot(struct iio_dev*, const unsigned long int*)'
  'bool input_device_enabled(struct input_dev*)'
  'void input_set_poll_interval(struct input_dev*, unsigned int)'
  'int input_setup_polling(struct input_dev*, void(*)(struct input_dev*))'
  'struct io_cq* ioc_lookup_icq(struct io_context*, struct request_queue*)'
  'int iova_cache_get()'
  'void iova_cache_put()'
  'void irq_domain_associate_many(struct irq_domain*, unsigned int, irq_hw_number_t, int)'
  'void iterate_supers_type(struct file_system_type*, void(*)(struct super_block*, void*), void*)'
  'void kill_litter_super(struct super_block*)'
  'int mmc_set_blocklen(struct mmc_card*, unsigned int)'
  'int netdev_set_num_tc(struct net_device*, u8)'
  'int netdev_set_tc_queue(struct net_device*, u8, u16, u16)'
  'struct net_device* netdev_upper_get_next_dev_rcu(struct net_device*, struct list_head**)'
  'unsigned long int nr_free_buffer_pages()'
  'int of_pci_get_max_link_speed(struct device_node*)'
  'bool pci_ats_supported(struct pci_dev*)'
  'void pci_disable_ats(struct pci_dev*)'
  'int pci_enable_ats(struct pci_dev*, int)'
  'int rpmsg_rx_done(struct rpmsg_endpoint*, void*)'
  'int scsi_register_driver(struct device_driver*)'
  'void sdhci_adma_write_desc(struct sdhci_host*, void**, dma_addr_t, int, unsigned int)'
  'void sdhci_set_uhs_signaling(struct sdhci_host*, unsigned int)'
  'size_t sg_copy_buffer(struct scatterlist*, unsigned int, void*, size_t, off_t, bool)'
  'size_t sg_zero_buffer(struct scatterlist*, unsigned int, size_t, off_t)'
  'int simple_statfs(struct dentry*, struct kstatfs*)'
  'int sysfs_create_mount_point(struct kobject*, const char*)'
  'void sysfs_remove_mount_point(struct kobject*, const char*)'
  'unsigned char tty_get_char_size(unsigned int)'
  'int ufshcd_system_freeze(struct device*)'
  'int ufshcd_system_restore(struct device*)'
  'int ufshcd_system_thaw(struct device*)'
  'int usbnet_get_ethernet_addr(struct usbnet*, int)'
  'void zap_vma_ptes(struct vm_area_struct*, unsigned long int, unsigned long int)'

16 variable symbol(s) added
  'struct tracepoint __tracepoint_android_vh_modify_thermal_throttle_update'
  'struct tracepoint __tracepoint_android_vh_mpam_set'
  'struct tracepoint __tracepoint_android_vh_mutex_can_spin_on_owner'
  'struct tracepoint __tracepoint_android_vh_mutex_opt_spin_finish'
  'struct tracepoint __tracepoint_android_vh_mutex_opt_spin_start'
  'struct tracepoint __tracepoint_android_vh_psi_group'
  'struct tracepoint __tracepoint_android_vh_rwsem_can_spin_on_owner'
  'struct tracepoint __tracepoint_android_vh_rwsem_opt_spin_finish'
  'struct tracepoint __tracepoint_android_vh_rwsem_opt_spin_start'
  'struct tracepoint __tracepoint_wbc_writepage'
  'struct static_key_true io_cgrp_subsys_on_dfl_key'
  'const unsigned char pcie_link_speed[16]'
  'unsigned long int phy_basic_features[2]'
  'unsigned long int phy_gbit_features[2]'
  'const struct inode_operations simple_dir_inode_operations'
  'const struct file_operations simple_dir_operations'

type 'enum bpf_prog_type' changed
  enumerator 'BPF_PROG_TYPE_FUSE' (32) was added

Change-Id: Icab4315e6ba42d246424150be9dbd58a8bd98133
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman
2023-03-27 13:19:01 +00:00
149 changed files with 19359 additions and 3901 deletions

View File

@@ -22,6 +22,7 @@ _aarch64_additional_kmi_symbol_lists = [
"android/abi_gki_aarch64_general",
"android/abi_gki_aarch64_honor",
"android/abi_gki_aarch64_imx",
"android/abi_gki_aarch64_lenovo",
"android/abi_gki_aarch64_mtk",
"android/abi_gki_aarch64_mtktv",
"android/abi_gki_aarch64_oplus",
@@ -38,6 +39,7 @@ _aarch64_additional_kmi_symbol_lists = [
"android/abi_gki_aarch64_virtual_device_removed",
"android/abi_gki_aarch64_vivo",
"android/abi_gki_aarch64_xiaomi",
"android/abi_gki_aarch64_zeku",
]
define_common_kernels(target_configs = {

View File

@@ -197,7 +197,7 @@ Description: Specific MJPEG format descriptors
read-only
bmaControls this format's data for bmaControls in
the streaming header
bmInterfaceFlags specifies interlace information,
bmInterlaceFlags specifies interlace information,
read-only
bAspectRatioY the X dimension of the picture aspect
ratio, read-only
@@ -253,7 +253,7 @@ Description: Specific uncompressed format descriptors
read-only
bmaControls this format's data for bmaControls in
the streaming header
bmInterfaceFlags specifies interlace information,
bmInterlaceFlags specifies interlace information,
read-only
bAspectRatioY the X dimension of the picture aspect
ratio, read-only

View File

@@ -0,0 +1,19 @@
What: /sys/block/dm-<num>/bow/free
Date: January 2023
KernelVersion: 5.15
Contact: paullawrence@google.com
Description: free space
Free space on device in bytes. Only valid in state 0
Users: Android vold to determine if there is sufficient space for expected size
of checksum
What: /sys/block/dm-<num>/bow/state
Date: January 2023
KernelVersion: 5.15
Contact: paullawrence@google.com
Description: dm-bow state
Read-write string containing 0, 1 or 2
0: Trim mode
1: Checkpoint mode
2: Committed mode
See Documentation/device-mapper/dm-bow for details

View File

@@ -0,0 +1,19 @@
What: /sys/fs/fuse/features/fuse_bpf
Date: December 2022
Contact: Paul Lawrence <paullawrence@google.com>
Description:
Read-only file that contains the word 'supported' if fuse-bpf is
supported, does not exist otherwise
What: /sys/fs/fuse/bpf_prog_type_fuse
Date: December 2022
Contact: Paul Lawrence <paullawrence@google.com>
Description:
bpf_prog_type_fuse defines the program type of bpf programs that
may be passed to fuse-bpf. For upstream bpf program types, this
is a constant defined in a contiguous array of constants.
bpf_prog_type_fuse is appended to the end of the list, so it may
change and therefore its value must be read from this file.
Contents is ASCII decimal representation of bpf_prog_type_fuse

View File

@@ -15,6 +15,12 @@ Contact: Paul Lawrence <paullawrence@google.com>
Description: Reads 'supported'. Present if zstd compression is supported
for data blocks.
What: /sys/fs/incremental-fs/features/bugfix_throttling
Date: January 2023
Contact: Paul Lawrence <paullawrence@google.com>
Description: Reads 'supported'. Present if the throttling lock bug is fixed
https://android-review.git.corp.google.com/c/kernel/common/+/2381827
What: /sys/fs/incremental-fs/instances/[name]
Date: April 2021
Contact: Paul Lawrence <paullawrence@google.com>

View File

@@ -0,0 +1,99 @@
dm_bow (backup on write)
========================
dm_bow is a device mapper driver that uses the free space on a device to back up
data that is overwritten. The changes can then be committed by a simple state
change, or rolled back by removing the dm_bow device and running a command line
utility over the underlying device.
dm_bow has three states, set by writing 1 or 2 to /sys/block/dm-?/bow/state.
It is only possible to go from state 0 (initial state) to state 1, and then from
state 1 to state 2.
State 0: dm_bow collects all trims to the device and assumes that these mark
free space on the overlying file system that can be safely used. Typically the
mount code would create the dm_bow device, mount the file system, call the
FITRIM ioctl on the file system then switch to state 1. These trims are not
propagated to the underlying device.
State 1: All writes to the device cause the underlying data to be backed up to
the free (trimmed) area as needed in such a way as they can be restored.
However, the writes, with one exception, then happen exactly as they would
without dm_bow, so the device is always in a good final state. The exception is
that sector 0 is used to keep a log of the latest changes, both to indicate that
we are in this state and to allow rollback. See below for all details. If there
isn't enough free space, writes are failed with -ENOSPC.
State 2: The transition to state 2 triggers replacing the special sector 0 with
the normal sector 0, and the freeing of all state information. dm_bow then
becomes a pass-through driver, allowing the device to continue to be used with
minimal performance impact.
Usage
=====
dm-bow takes one command line parameter, the name of the underlying device.
dm-bow will typically be used in the following way. dm-bow will be loaded with a
suitable underlying device and the resultant device will be mounted. A file
system trim will be issued via the FITRIM ioctl, then the device will be
switched to state 1. The file system will now be used as normal. At some point,
the changes can either be committed by switching to state 2, or rolled back by
unmounting the file system, removing the dm-bow device and running the command
line utility. Note that rebooting the device will be equivalent to unmounting
and removing, but the command line utility must still be run
Details of operation in state 1
===============================
dm_bow maintains a type for all sectors. A sector can be any of:
SECTOR0
SECTOR0_CURRENT
UNCHANGED
FREE
CHANGED
BACKUP
SECTOR0 is the first sector on the device, and is used to hold the log of
changes. This is the one exception.
SECTOR0_CURRENT is a sector picked from the FREE sectors, and is where reads and
writes from the true sector zero are redirected to. Note that like any backup
sector, if the sector is written to directly, it must be moved again.
UNCHANGED means that the sector has not been changed since we entered state 1.
Thus if it is written to or trimmed, the contents must first be backed up.
FREE means that the sector was trimmed in state 0 and has not yet been written
to or used for backup. On being written to, a FREE sector is changed to CHANGED.
CHANGED means that the sector has been modified, and can be further modified
without further backup.
BACKUP means that this is a free sector being used as a backup. On being written
to, the contents must first be backed up again.
All backup operations are logged to the first sector. The log sector has the
format:
--------------------------------------------------------
| Magic | Count | Sequence | Log entry | Log entry | …
--------------------------------------------------------
Magic is a magic number. Count is the number of log entries. Sequence is 0
initially. A log entry is
-----------------------------------
| Source | Dest | Size | Checksum |
-----------------------------------
When SECTOR0 is full, the log sector is backed up and another empty log sector
created with sequence number one higher. The first entry in any log entry with
sequence > 0 therefore must be the log of the backing up of the previous log
sector. Note that sequence is not strictly needed, but is a useful sanity check
and potentially limits the time spent trying to restore a corrupted snapshot.
On entering state 1, dm_bow has a list of free sectors. All other sectors are
unchanged. Sector0_current is selected from the free sectors and the contents of
sector 0 are copied there. The sector 0 is backed up, which triggers the first
log entry to be written.

View File

@@ -35,6 +35,9 @@ Features
/sys/fs/incremental-fs/features/zstd
Reads 'supported'. Present if zstd compression is supported for data blocks.
/sys/fs/incremental-fs/features/bugfix_throttling
Reads 'supported'. Present if the throttling lock bug is fixed
Optional per mount
------------------

File diff suppressed because it is too large Load Diff

View File

@@ -334,6 +334,7 @@
devm_nvmem_cell_get
devm_of_clk_add_hw_provider
devm_of_pwm_get
devm_pci_remap_cfg_resource
devm_phy_get
devm_pinctrl_get
devm_pinctrl_put

View File

@@ -168,10 +168,6 @@
dev_pm_opp_put
dev_pm_opp_set_opp
dev_pm_opp_set_rate
devres_add
__devres_alloc_node
devres_free
devres_release
dev_set_name
_dev_warn
disable_irq
@@ -1025,13 +1021,6 @@
# required by icc-osm-l3.ko
icc_std_aggregate
# required by led-class-multicolor.ko
led_classdev_register_ext
led_classdev_unregister
led_colors
led_set_brightness
stpcpy
# required by llcc-qcom.ko
devm_platform_ioremap_resource_byname
@@ -1755,6 +1744,12 @@
__xa_insert
xa_load
# required by reboot-mode.ko
devres_add
__devres_alloc_node
devres_free
devres_release
# required by regmap-spmi.ko
spmi_ext_register_read
spmi_ext_register_readl
@@ -1927,8 +1922,11 @@
ufshcd_runtime_resume
ufshcd_runtime_suspend
ufshcd_suspend_prepare
ufshcd_system_freeze
ufshcd_system_restore
ufshcd_system_resume
ufshcd_system_suspend
ufshcd_system_thaw
# required by ulpi.ko
of_device_modalias
@@ -2010,7 +2008,12 @@
# preserved by --additions-only
drm_connector_init_with_ddc
led_classdev_register_ext
led_classdev_unregister
led_colors
led_set_brightness
of_clk_get_by_name
snd_soc_get_volsw_sx
snd_soc_info_volsw_sx
snd_soc_put_volsw_sx
stpcpy

View File

@@ -0,0 +1,956 @@
[abi_symbol_list]
# commonly used symbols
alloc_chrdev_region
__alloc_pages
__alloc_skb
alloc_workqueue
android_kmalloc_64_create
__arch_copy_from_user
__arch_copy_to_user
arm64_const_caps_ready
arm64_use_ng_mappings
bcmp
bitmap_find_free_region
bitmap_release_region
bitmap_zalloc
bpf_trace_run1
bpf_trace_run2
bpf_trace_run3
bpf_trace_run4
bpf_trace_run5
bus_for_each_dev
cancel_delayed_work
cancel_delayed_work_sync
cancel_work_sync
cdev_add
cdev_del
cdev_init
__cfi_slowpath_diag
__check_object_size
__class_create
class_destroy
__class_register
class_unregister
__ClearPageMovable
clk_disable
clk_enable
clk_get_rate
clk_prepare
clk_put
clk_unprepare
cma_alloc
cma_release
complete
complete_all
__const_udelay
consume_skb
cpu_bit_bitmap
__cpuhp_remove_state
__cpuhp_setup_state
__cpuhp_state_add_instance
__cpuhp_state_remove_instance
cpu_hwcap_keys
cpu_hwcaps
cpumask_next
cpu_number
__cpu_online_mask
__cpu_possible_mask
_ctype
debugfs_attr_read
debugfs_attr_write
debugfs_create_dir
debugfs_create_file
debugfs_remove
default_llseek
delayed_work_timer_fn
del_timer_sync
destroy_workqueue
dev_close
dev_driver_string
_dev_err
device_create
device_destroy
device_initialize
device_property_present
device_property_read_u32_array
_dev_info
devm_gpiod_get_optional
devm_ioremap
devm_ioremap_resource
devm_kfree
devm_kmalloc
devm_platform_ioremap_resource
__devm_regmap_init
__devm_request_region
devm_request_threaded_irq
_dev_notice
dev_set_name
_dev_warn
disable_irq
dma_alloc_attrs
dma_buf_attach
dma_buf_detach
dma_buf_export
dma_buf_get
dma_buf_map_attachment
dma_buf_put
dma_buf_unmap_attachment
dma_contiguous_default_area
dma_free_attrs
dma_heap_add
dma_heap_get_drvdata
dma_heap_get_name
dmam_alloc_attrs
dma_map_page_attrs
dma_map_sgtable
dmam_free_coherent
dma_set_coherent_mask
dma_set_mask
dma_sync_sg_for_cpu
dma_sync_sg_for_device
dma_sync_single_for_device
dma_unmap_page_attrs
dma_unmap_sg_attrs
down_interruptible
down_read
down_write
dump_stack
enable_irq
eth_type_trans
event_triggers_call
_find_first_bit
_find_first_zero_bit
__find_vma
finish_wait
flush_work
free_irq
__free_pages
free_pages
gcd
__get_free_pages
gic_nonsecure_priorities
hrtimer_cancel
hrtimer_forward
hrtimer_init
hrtimer_start_range_ns
i2c_get_adapter
i2c_put_adapter
i2c_transfer
init_net
__init_rwsem
__init_swait_queue_head
init_timer_key
init_wait_entry
__init_waitqueue_head
iomem_resource
__ioremap
iounmap
iput
irq_get_irq_data
irq_of_parse_and_map
irq_set_affinity
is_vmalloc_addr
jiffies
jiffies_to_msecs
kasan_flag_enabled
kfree
kfree_skb
kimage_voffset
__kmalloc
kmalloc_caches
kmalloc_order_trace
kmem_cache_alloc_trace
kobject_create_and_add
kobject_init_and_add
kobject_put
kstrdup
kstrtoint
kstrtoint_from_user
kstrtouint
kstrtoull
kthread_create_on_node
kthread_should_stop
kthread_stop
ktime_get
ktime_get_mono_fast_ns
ktime_get_real_ts64
ktime_get_with_offset
kvfree
kvmalloc_node
__list_add_valid
__list_del_entry_valid
log_post_read_mmio
log_post_write_mmio
log_read_mmio
log_write_mmio
memcmp
memcpy
memdup_user
memmove
memset
memstart_addr
misc_deregister
misc_register
mod_delayed_work_on
mod_timer
module_layout
__msecs_to_jiffies
msleep
__mutex_init
mutex_is_locked
mutex_lock
mutex_unlock
__netdev_alloc_skb
netif_rx_ni
netlink_unicast
nla_put
no_llseek
nr_cpu_ids
of_address_to_resource
of_device_is_compatible
of_dma_is_coherent
of_find_device_by_node
of_find_property
of_get_child_by_name
of_get_next_available_child
of_get_next_child
of_iomap
of_irq_get
of_parse_phandle
of_property_read_string
of_property_read_variable_u32_array
of_reserved_mem_lookup
panic
param_ops_bool
param_ops_charp
param_ops_int
param_ops_string
param_ops_uint
param_ops_ulong
param_ops_ushort
pci_disable_device
pci_enable_device
pci_find_capability
pci_get_device
pci_set_power_state
__per_cpu_offset
perf_trace_buf_alloc
perf_trace_run_bpf_submit
pfn_is_map_memory
platform_device_register
platform_device_unregister
__platform_driver_register
platform_driver_unregister
platform_get_irq
platform_get_irq_byname
platform_get_irq_byname_optional
platform_get_resource
__pm_runtime_disable
pm_runtime_enable
__pm_runtime_idle
__pm_runtime_resume
__pm_runtime_set_status
__pm_runtime_suspend
preempt_schedule
preempt_schedule_notrace
prepare_to_wait_event
_printk
proc_create
put_device
__put_page
__put_task_struct
queue_delayed_work_on
queue_work_on
___ratelimit
_raw_spin_lock
_raw_spin_lock_bh
_raw_spin_lock_irqsave
_raw_spin_unlock
_raw_spin_unlock_bh
_raw_spin_unlock_irqrestore
rb_erase
rb_insert_color
__rcu_read_lock
__rcu_read_unlock
refcount_warn_saturate
register_chrdev_region
register_netdevice
register_netdevice_notifier
register_shrinker
regmap_read
regmap_write
release_firmware
__release_region
remap_pfn_range
request_firmware
__request_region
request_threaded_irq
reset_control_assert
reset_control_deassert
rfkill_alloc
rfkill_destroy
rfkill_register
rfkill_unregister
rtnl_is_locked
rtnl_lock
rtnl_unlock
sched_clock
schedule
schedule_timeout
scnprintf
seq_lseek
seq_open
seq_printf
seq_puts
seq_read
seq_release
__SetPageMovable
sg_alloc_table
sg_alloc_table_from_pages_segment
sg_free_table
sg_next
simple_attr_open
simple_attr_release
simple_open
simple_read_from_buffer
single_open
single_release
skb_pull
skb_push
snprintf
sprintf
sscanf
__stack_chk_fail
strcmp
strcpy
strlcpy
strlen
strncmp
strncpy
strnlen
strstr
__sw_hweight32
__sw_hweight64
synchronize_net
synchronize_rcu
sysfs_create_file_ns
sysfs_create_group
sysfs_emit
sysfs_remove_group
sysfs_streq
system_wq
trace_event_buffer_commit
trace_event_buffer_reserve
trace_event_ignore_this_pid
trace_event_printf
trace_event_raw_init
trace_event_reg
trace_handle_return
trace_print_array_seq
trace_raw_output_prep
__ubsan_handle_cfi_check_fail_abort
__udelay
unlock_page
__unregister_chrdev
unregister_chrdev_region
unregister_netdevice_notifier
unregister_netdevice_queue
unregister_shrinker
up
up_read
up_write
usleep_range_state
vabits_actual
vfree
vmalloc
vmap
vmf_insert_pfn_prot
vsnprintf
vunmap
vzalloc
wait_for_completion_timeout
__wake_up
wake_up_process
__warn_printk
# required by access_monitor.ko
devm_iounmap
devm_of_iomap
of_property_read_string_helper
# required by arm_dsu_pmu.ko
bitmap_from_arr32
bitmap_print_to_pagebuf
cpumask_any_but
dev_fwnode
devm_kasprintf
of_count_phandle_with_args
of_cpu_node_to_id
of_fwnode_ops
perf_event_update_userpage
perf_pmu_migrate_context
perf_pmu_register
perf_pmu_unregister
# required by arm_smmu_v3.ko
alloc_io_pgtable_ops
amba_bustype
bitmap_free
bus_set_iommu
device_match_fwnode
devm_add_action
driver_find_device
free_io_pgtable_ops
generic_device_group
generic_iommu_put_resv_regions
iommu_alloc_resv_region
iommu_device_register
iommu_device_sysfs_add
iommu_device_sysfs_remove
iommu_device_unregister
iommu_dma_get_resv_regions
iommu_fwspec_add_ids
iommu_fwspec_free
iommu_report_device_fault
of_find_node_with_property
of_parse_phandle_with_args
pci_ats_supported
pci_bus_type
pci_device_group
pci_disable_ats
pci_enable_ats
platform_bus_type
platform_msi_domain_alloc_irqs
platform_msi_domain_free_irqs
__xa_alloc
xa_erase
# required by bcmdhd.ko
add_timer
alloc_etherdev_mqs
bitmap_parse
capable
complete_and_exit
del_timer
__dev_kfree_skb_any
disable_irq_nosync
down
free_netdev
get_random_bytes
get_random_u32
gpiod_direction_output_raw
gpio_free
gpio_to_desc
iwe_stream_add_event
iwe_stream_add_point
iwe_stream_add_value
__kfifo_free
__kfifo_in
__kfifo_init
__kfifo_out
kobject_uevent
__local_bh_enable_ip
napi_complete_done
napi_disable
napi_enable
napi_gro_receive
__napi_schedule
napi_schedule_prep
netdev_update_features
netif_napi_add
__netif_napi_del
netif_receive_skb
netif_rx
netif_tx_wake_queue
__netlink_kernel_create
netlink_kernel_release
nla_put_nohdr
__nlmsg_put
ns_to_timespec64
pci_alloc_irq_vectors_affinity
pci_enable_wake
pci_find_ext_capability
pci_free_irq_vectors
pci_load_and_free_saved_state
pci_load_saved_state
pci_read_config_dword
__pci_register_driver
pci_restore_state
pci_save_state
pci_set_master
pci_store_saved_state
pci_unregister_driver
pci_write_config_dword
__pm_relax
__pm_stay_awake
pm_wakeup_ws_event
pskb_expand_head
register_inetaddr_notifier
register_netdev
register_pm_notifier
register_reboot_notifier
rtc_time64_to_tm
sched_set_fifo_low
set_cpus_allowed_ptr
simple_strtol
simple_strtoul
skb_clone
skb_copy
skb_dequeue
skb_queue_purge
skb_queue_tail
sock_wfree
sprint_symbol
strcat
strchr
strncasecmp
strncat
strrchr
strsep
strspn
sys_tz
tasklet_init
tasklet_kill
__tasklet_schedule
unregister_inetaddr_notifier
unregister_netdev
unregister_pm_notifier
unregister_reboot_notifier
vprintk
wakeup_source_register
wakeup_source_unregister
wireless_send_event
work_busy
# required by cfg80211.ko
bpf_trace_run10
bpf_trace_run6
bpf_trace_run7
bpf_trace_run8
crc32_le
debugfs_rename
__dev_change_net_namespace
__dev_get_by_index
dev_get_by_index
device_add
device_del
device_rename
do_trace_netlink_extack
flush_delayed_work
genlmsg_multicast_allns
genlmsg_put
genl_register_family
genl_unregister_family
get_net_ns_by_fd
get_net_ns_by_pid
inet_csk_get_port
init_uts_ns
key_create_or_update
key_put
keyring_alloc
kfree_sensitive
kmemdup
kobject_uevent_env
ktime_get_coarse_with_offset
kvfree_call_rcu
netdev_err
netlink_broadcast
netlink_register_notifier
netlink_unregister_notifier
net_ns_type_operations
nla_find
nla_memcpy
__nla_parse
nla_put_64bit
nla_reserve
__nla_validate
of_prop_next_u32
platform_device_register_full
__pskb_pull_tail
__put_net
register_pernet_device
request_firmware_nowait
rfkill_blocked
rfkill_resume_polling
rfkill_set_hw_state_reason
skb_add_rx_frag
skb_copy_bits
skb_put
skb_trim
__sock_create
sock_release
__sw_hweight16
__sw_hweight8
sysfs_create_link
sysfs_remove_link
system_power_efficient_wq
unregister_pernet_device
verify_pkcs7_signature
wireless_nlevent_flush
# required by ci700.ko
__arm_smccc_smc
kernel_kobj
of_device_is_available
of_find_matching_node_and_match
PDE_DATA
proc_mkdir
# required by cma_heap.ko
cma_get_name
# required by dma-buf-test-exporter.ko
dma_buf_begin_cpu_access
dma_buf_end_cpu_access
dma_buf_fd
dma_map_sg_attrs
# required by dwc3-smartsilicon.ko
device_set_wakeup_capable
irq_set_irq_wake
of_get_compatible_child
of_platform_depopulate
of_platform_populate
sysfs_create_groups
usb_speed_string
# required by fr.ko
find_task_by_vpid
iommu_get_domain_for_dev
iommu_iova_to_phys
remove_proc_entry
# required by hantrodec.ko
of_dma_configure_id
vmalloc_to_page
# required by hantroenc.ko
__register_chrdev
# required by i2c-designware-core.ko
i2c_add_numbered_adapter
i2c_generic_scl_recovery
i2c_recover_bus
regmap_update_bits_base
# required by i2c-designware-platform.ko
device_get_match_data
devm_clk_get_optional
__devm_reset_control_get
i2c_del_adapter
i2c_parse_fw_timings
pm_runtime_set_autosuspend_delay
__pm_runtime_use_autosuspend
pm_suspend_global_flags
syscon_node_to_regmap
# required by i2c-dev.ko
bus_register_notifier
bus_unregister_notifier
cdev_device_add
cdev_device_del
device_for_each_child
i2c_adapter_type
i2c_bus_type
i2c_for_each_dev
i2c_smbus_xfer
i2c_transfer_buffer_flags
i2c_verify_client
# required by kutf.ko
debugfs_create_file_unsafe
debugfs_create_u32
strnchr
strpbrk
# required by mali_kbase.ko
anon_inode_getfd
__arch_clear_user
__bitmap_andnot
__bitmap_equal
__bitmap_or
__bitmap_weight
__bitmap_xor
cache_line_size
clear_page
__clk_is_enabled
clk_notifier_register
clk_notifier_unregister
clk_set_rate
completion_done
debugfs_create_bool
devfreq_add_device
devfreq_cooling_unregister
devfreq_recommended_opp
devfreq_register_opp_notifier
devfreq_remove_device
devfreq_resume_device
devfreq_suspend_device
devfreq_unregister_opp_notifier
device_create_file
device_remove_file
dev_pm_opp_find_freq_ceil
dev_pm_opp_find_freq_exact
dev_pm_opp_find_freq_floor
dev_pm_opp_get_opp_count
dev_pm_opp_get_voltage
dev_pm_opp_of_add_table
dev_pm_opp_of_remove_table
dev_pm_opp_put
dev_pm_opp_put_regulators
dev_pm_opp_set_regulators
dma_buf_mmap
dma_fence_add_callback
dma_fence_context_alloc
dma_fence_default_wait
dma_fence_get_status
dma_fence_init
dma_fence_release
dma_fence_remove_callback
dma_fence_signal
dma_sync_single_for_cpu
downgrade_write
down_read_trylock
fd_install
find_get_pid
_find_next_bit
flush_workqueue
fput
generic_file_llseek
get_device
get_unused_fd_flags
get_user_pages
get_user_pages_fast
hrtimer_active
kobject_del
kstrndup
kstrtobool_from_user
kstrtouint_from_user
ktime_get_raw
ktime_get_raw_ts64
__lock_page
memchr
__mmdrop
module_put
msleep_interruptible
mutex_trylock
nonseekable_open
of_clk_get
of_devfreq_cooling_register_power
of_find_compatible_node
of_get_property
of_machine_is_compatible
of_property_count_elems_of_size
of_property_read_u64
of_property_read_variable_u64_array
of_property_read_variable_u8_array
param_array_ops
param_ops_byte
pid_task
pin_user_pages
pin_user_pages_remote
put_pid
_raw_spin_trylock
rb_first
rb_next
rb_prev
rb_replace_node
register_oom_notifier
regulator_disable
regulator_enable
regulator_get_optional
regulator_put
regulator_set_voltage
remap_vmalloc_range
__seq_open_private
seq_putc
seq_release_private
seq_write
set_page_dirty_lock
shmem_file_setup
strcspn
strscpy
sync_file_create
sync_file_get_fence
synchronize_irq
sysfs_remove_file_ns
system_highpri_wq
system_long_wq
thermal_zone_get_zone_by_name
_totalram_pages
__traceiter_gpu_mem_total
trace_output_call
__tracepoint_gpu_mem_total
trace_print_flags_seq
trace_print_symbols_seq
try_module_get
unmap_mapping_range
unpin_user_page
unregister_oom_notifier
vmalloc_user
wait_for_completion
# required by pcie-smsi.ko
cpumask_next_and
device_init_wakeup
device_release_driver
devm_pci_alloc_host_bridge
devm_pci_remap_cfg_resource
devm_release_resource
generic_handle_domain_irq
generic_handle_irq
gpiod_get_value
gpiod_set_value_cansleep
handle_edge_irq
handle_simple_irq
__irq_alloc_descs
irq_chip_ack_parent
irq_chip_mask_parent
irq_chip_unmask_parent
irq_dispose_mapping
__irq_domain_add
irq_domain_associate_many
irq_domain_get_irq_data
irq_domain_remove
irq_domain_set_info
irq_domain_update_bus_token
__irq_resolve_mapping
irq_set_chained_handler_and_data
irq_set_chip_and_handler_name
irq_set_chip_data
irq_to_desc
nr_irqs
of_match_device
of_pci_get_max_link_speed
pci_disable_link_state
pcie_capability_clear_and_set_word
pcie_link_speed
pci_generic_config_read
pci_generic_config_write
pci_host_probe
pci_lock_rescan_remove
pci_msi_create_irq_domain
pci_msi_enabled
pci_msi_mask_irq
pci_msi_unmask_irq
pci_pio_to_address
pci_read_config_byte
pci_read_config_word
pci_remove_root_bus
pci_stop_root_bus
pci_unlock_rescan_remove
platform_get_resource_byname
simple_write_to_buffer
# required by smsi-mailbox-ap2rpm.ko
mbox_free_channel
mbox_request_channel_byname
# required by smsi-mailbox.ko
devm_mbox_controller_register
mbox_chan_received_data
__memcpy_fromio
__memcpy_toio
# required by smsi_busmon.ko
arch_timer_read_counter
# required by smsi_wdt.ko
autoremove_wake_function
irq_force_affinity
kthread_bind
of_irq_parse_one
prepare_to_wait
sched_set_fifo
watchdog_init_timeout
watchdog_register_device
watchdog_set_restart_priority
watchdog_unregister_device
# required by system_heap.ko
dmabuf_page_pool_alloc
dmabuf_page_pool_create
dmabuf_page_pool_destroy
dmabuf_page_pool_free
dma_heap_get_dev
__sg_page_iter_next
__sg_page_iter_start
# required by vvcam_dw200.ko
devm_free_irq
# required by vvcam_sensor.ko
i2c_new_client_device
i2c_unregister_device
# required by zram.ko
__alloc_percpu
bio_endio
bio_end_io_acct_remapped
bio_start_io_acct
__blk_alloc_disk
blk_cleanup_disk
blk_queue_flag_clear
blk_queue_flag_set
blk_queue_io_min
blk_queue_io_opt
blk_queue_logical_block_size
blk_queue_max_discard_sectors
blk_queue_max_write_zeroes_sectors
blk_queue_physical_block_size
crypto_alloc_base
crypto_comp_compress
crypto_comp_decompress
crypto_destroy_tfm
crypto_has_alg
del_gendisk
device_add_disk
disk_end_io_acct
disk_start_io_acct
flush_dcache_page
free_percpu
fsync_bdev
idr_alloc
idr_destroy
idr_find
idr_for_each
idr_remove
kstrtou16
memparse
memset64
__num_online_cpus
page_endio
__register_blkdev
set_capacity
set_capacity_and_notify
unregister_blkdev
zs_compact
zs_create_pool
zs_destroy_pool
zs_free
zs_get_total_pages
zs_huge_class_size
zs_malloc
zs_map_object
zs_pool_stats
zs_unmap_object
# required by zsmalloc.ko
alloc_anon_inode
contig_page_data
dec_zone_page_state
inc_zone_page_state
init_pseudo
kern_mount
kern_unmount
kill_anon_super
kmem_cache_alloc
kmem_cache_create
kmem_cache_destroy
kmem_cache_free
page_mapping
_raw_read_lock
_raw_read_unlock
_raw_write_lock
_raw_write_unlock
wait_on_page_bit

View File

@@ -1249,6 +1249,7 @@
__netdev_alloc_skb
netdev_err
netdev_info
netdev_upper_get_next_dev_rcu
netdev_warn
netif_carrier_off
netif_carrier_on
@@ -1419,6 +1420,7 @@
perf_trace_run_bpf_submit
pfn_is_map_memory
phy_attached_info
phy_basic_features
phy_connect
phy_disconnect
phy_do_ioctl_running
@@ -1426,6 +1428,7 @@
phy_ethtool_nway_reset
phy_ethtool_set_link_ksettings
phy_exit
phy_gbit_features
phy_get
phy_init
phy_loopback
@@ -2153,6 +2156,7 @@
tty_chars_in_buffer
tty_driver_flush_buffer
tty_flip_buffer_push
tty_get_char_size
tty_insert_flip_string_fixed_flag
tty_ldisc_flush
tty_register_ldisc
@@ -2304,6 +2308,7 @@
usbnet_disconnect
usbnet_get_drvinfo
usbnet_get_endpoints
usbnet_get_ethernet_addr
usbnet_get_link
usbnet_get_link_ksettings_mii
usbnet_get_msglevel

View File

@@ -415,6 +415,9 @@
__traceiter_android_vh_meminfo_proc_show
__traceiter_android_vh_modify_thermal_cpu_get_power
__traceiter_android_vh_mutex_init
__traceiter_android_vh_mutex_can_spin_on_owner
__traceiter_android_vh_mutex_opt_spin_finish
__traceiter_android_vh_mutex_opt_spin_start
__traceiter_android_vh_page_referenced_check_bypass
__traceiter_android_vh_page_should_be_protected
__traceiter_android_vh_page_trylock_clear
@@ -427,6 +430,9 @@
__traceiter_android_vh_record_rtmutex_lock_starttime
__traceiter_android_vh_record_rwsem_lock_starttime
__traceiter_android_vh_rmqueue
__traceiter_android_vh_rwsem_can_spin_on_owner
__traceiter_android_vh_rwsem_opt_spin_finish
__traceiter_android_vh_rwsem_opt_spin_start
__traceiter_android_vh_rwsem_wake_finish
__traceiter_android_vh_save_track_hash
__traceiter_android_vh_sched_show_task
@@ -500,6 +506,9 @@
__tracepoint_android_vh_meminfo_proc_show
__tracepoint_android_vh_modify_thermal_cpu_get_power
__tracepoint_android_vh_mutex_init
__tracepoint_android_vh_mutex_can_spin_on_owner
__tracepoint_android_vh_mutex_opt_spin_finish
__tracepoint_android_vh_mutex_opt_spin_start
__tracepoint_android_vh_page_referenced_check_bypass
__tracepoint_android_vh_page_should_be_protected
__tracepoint_android_vh_page_trylock_clear
@@ -512,6 +521,9 @@
__tracepoint_android_vh_record_rtmutex_lock_starttime
__tracepoint_android_vh_record_rwsem_lock_starttime
__tracepoint_android_vh_rmqueue
__tracepoint_android_vh_rwsem_can_spin_on_owner
__tracepoint_android_vh_rwsem_opt_spin_finish
__tracepoint_android_vh_rwsem_opt_spin_start
__tracepoint_android_vh_rwsem_wake_finish
__tracepoint_android_vh_sched_show_task
__tracepoint_android_vh_save_track_hash

View File

@@ -14,3 +14,5 @@
hid_report_raw_event
hid_unregister_driver
hidinput_calc_abs_res
iio_trigger_generic_data_rdy_poll
input_device_enabled

View File

@@ -89,6 +89,7 @@
__blk_alloc_disk
blk_cleanup_disk
blk_cleanup_queue
blkdev_compat_ptr_ioctl
blkdev_get_by_dev
__blkdev_issue_discard
blkdev_put
@@ -140,7 +141,6 @@
blk_set_stacking_limits
blk_start_plug
blk_sync_queue
blkdev_compat_ptr_ioctl
blocking_notifier_call_chain
blocking_notifier_chain_register
blocking_notifier_chain_unregister
@@ -258,6 +258,7 @@
contig_page_data
_copy_from_iter
copy_from_kernel_nofault
copy_page
__cpu_active_mask
cpu_bit_bitmap
cpufreq_cpu_get
@@ -320,6 +321,7 @@
crypto_destroy_tfm
crypto_enqueue_request
crypto_has_alg
crypto_inc
crypto_init_queue
crypto_unregister_ahash
crypto_unregister_skcipher
@@ -418,6 +420,7 @@
devm_gpio_request_one
devm_hwspin_lock_register
devm_iio_channel_get
devm_iio_channel_get_all
devm_iio_device_alloc
__devm_iio_device_register
devm_input_allocate_device
@@ -491,10 +494,10 @@
dev_pm_opp_of_cpumask_remove_table
dev_pm_opp_of_find_icc_paths
dev_pm_opp_of_register_em
dev_pm_opp_remove
dev_pm_opp_of_remove_table
dev_pm_opp_put
dev_pm_opp_put_clkname
dev_pm_opp_remove
dev_pm_opp_remove_all_dynamic
dev_pm_opp_set_clkname
dev_pm_opp_set_opp
@@ -813,6 +816,7 @@
get_unused_fd_flags
get_user_ifreq
get_zeroed_page
gf128mul_lle
gic_cpu_init
gic_dist_init
gic_dist_wait_for_rwp
@@ -834,6 +838,7 @@
gpiod_direction_input
gpiod_direction_output
gpiod_direction_output_raw
gpiod_get_direction
gpiod_get_optional
gpiod_get_raw_value
gpiod_get_value
@@ -929,16 +934,35 @@
idr_preload
idr_remove
idr_replace
iio_alloc_pollfunc
iio_buffer_init
iio_buffer_put
iio_channel_get
iio_channel_get_all
iio_channel_release
iio_channel_release_all
iio_dealloc_pollfunc
iio_device_attach_buffer
iio_device_claim_direct_mode
iio_device_id
iio_device_release_direct_mode
iio_get_time_ns
iio_kfifo_allocate
iio_push_event
iio_push_to_buffers
iio_read_channel_processed
iio_read_channel_raw
iio_read_const_attr
iio_trigger_alloc
iio_triggered_buffer_cleanup
iio_triggered_buffer_setup_ext
iio_trigger_free
iio_trigger_notify_done
iio_trigger_poll
__iio_trigger_register
iio_trigger_unregister
iio_update_buffers
iio_validate_scan_mask_onehot
iio_write_channel_raw
import_iovec
in4_pton
@@ -973,6 +997,8 @@
input_register_handler
input_set_abs_params
input_set_capability
input_set_poll_interval
input_setup_polling
input_unregister_handle
input_unregister_handler
interval_tree_insert
@@ -1064,6 +1090,8 @@
irq_set_chained_handler_and_data
irq_set_chip_and_handler_name
irq_set_chip_data
__irq_set_handler
irq_set_handler_data
irq_set_irqchip_state
irq_set_irq_type
irq_set_irq_wake
@@ -1252,8 +1280,8 @@
misc_register
mmc_cqe_request_done
mmc_execute_tuning
mmc_get_ext_csd
mmc_get_card
mmc_get_ext_csd
mmc_hs200_tuning
mmc_issue_type
mmc_of_parse
@@ -1265,8 +1293,8 @@
mmc_regulator_set_vqmmc
mmc_retune_hold
mmc_retune_release
mmc_select_card
mmc_select_bus_width
mmc_select_card
mmc_select_hs
mmc_select_hs400
mmc_select_hs_ddr
@@ -1814,6 +1842,7 @@
rpmsg_get_signals
rpmsg_poll
rpmsg_register_device
rpmsg_rx_done
rpmsg_send
rpmsg_set_signals
rpmsg_trysend
@@ -2248,6 +2277,7 @@
__traceiter_android_vh_save_cpu_resume
__traceiter_android_vh_save_hib_resume_bdev
__traceiter_android_vh_scheduler_tick
__traceiter_android_vh_sd_update_bus_speed_mode
__traceiter_android_vh_show_resume_epoch_val
__traceiter_android_vh_show_suspend_epoch_val
__traceiter_android_vh_skip_swap_map_write
@@ -2268,6 +2298,8 @@
__traceiter_ipi_raise
__traceiter_irq_handler_entry
__traceiter_map
__traceiter_rwmmio_read
__traceiter_rwmmio_write
__traceiter_sched_overutilized_tp
__traceiter_sched_switch
__traceiter_suspend_resume
@@ -2367,6 +2399,7 @@
__tracepoint_android_vh_save_cpu_resume
__tracepoint_android_vh_save_hib_resume_bdev
__tracepoint_android_vh_scheduler_tick
__tracepoint_android_vh_sd_update_bus_speed_mode
__tracepoint_android_vh_show_resume_epoch_val
__tracepoint_android_vh_show_suspend_epoch_val
__tracepoint_android_vh_skip_swap_map_write
@@ -2390,6 +2423,8 @@
tracepoint_probe_register
tracepoint_probe_register_prio
tracepoint_probe_unregister
__tracepoint_rwmmio_read
__tracepoint_rwmmio_write
__tracepoint_sched_overutilized_tp
__tracepoint_sched_switch
__tracepoint_suspend_resume
@@ -2503,6 +2538,8 @@
usb_free_coherent
usb_function_register
usb_function_unregister
usb_gadget_connect
usb_gadget_disconnect
usb_gadget_wakeup
usb_ifnum_to_if
usb_interface_id
@@ -2630,3 +2667,4 @@
xsk_tx_peek_desc
xsk_tx_release
xsk_uses_need_wakeup
zap_vma_ptes

View File

@@ -287,6 +287,7 @@
devm_nvmem_register
devm_of_clk_add_hw_provider
devm_of_iomap
devm_pci_remap_cfgspace
devm_pinctrl_get
devm_pinctrl_put
devm_pinctrl_register
@@ -894,6 +895,7 @@
of_nvmem_cell_get
of_parse_phandle
of_parse_phandle_with_args
of_pci_get_max_link_speed
of_property_count_elems_of_size
of_property_match_string
of_property_read_string
@@ -941,6 +943,7 @@
pci_unregister_driver
pci_write_config_byte
pci_write_config_word
pcie_link_speed
PDE_DATA
__per_cpu_offset
perf_trace_buf_alloc

View File

@@ -1147,6 +1147,7 @@
__traceiter_android_vh_mmc_update_partition_status
__traceiter_android_vh_modify_thermal_request_freq
__traceiter_android_vh_modify_thermal_target_freq
__traceiter_android_vh_modify_thermal_throttle_update
__traceiter_android_vh_scheduler_tick
__traceiter_android_vh_set_wake_flags
__traceiter_android_vh_thermal_power_cap
@@ -1242,6 +1243,7 @@
__tracepoint_android_vh_mmc_update_partition_status
__tracepoint_android_vh_modify_thermal_request_freq
__tracepoint_android_vh_modify_thermal_target_freq
__tracepoint_android_vh_modify_thermal_throttle_update
__tracepoint_android_vh_scheduler_tick
__tracepoint_android_vh_set_wake_flags
__tracepoint_android_vh_thermal_power_cap

View File

@@ -335,6 +335,7 @@
del_gendisk
del_timer
del_timer_sync
dentry_path_raw
destroy_workqueue
dev_alloc_name
dev_coredumpm

View File

@@ -14,6 +14,8 @@
#required by memory module
blk_execute_rq
blk_rq_map_kern
nr_free_buffer_pages
mmc_set_blocklen
scsi_device_lookup
scsi_host_lookup
scsi_host_put
@@ -104,6 +106,21 @@
__traceiter_android_vh_direct_io_update_bio
__traceiter_android_vh_loop_prepare_cmd
#required by bfq module
__blkg_prfill_rwstat
blkg_rwstat_recursive_sum
blkg_prfill_rwstat
blkg_conf_finish
blkg_conf_prep
__blkg_prfill_u64
blkcg_print_blkgs
blkg_rwstat_exit
blkg_rwstat_init
percpu_counter_add_batch
io_cgrp_subsys_on_dfl_key
ioc_lookup_icq
bdi_dev_name
#required by cs35l41 module
regmap_raw_write_async
snd_soc_bytes_tlv_callback
@@ -523,3 +540,7 @@
__traceiter_android_rvh_ctl_dirty_rate
__tracepoint_android_rvh_ctl_dirty_rate
#required by io module
__traceiter_android_vh_psi_group
__tracepoint_android_vh_psi_group

1262
android/abi_gki_aarch64_zeku Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -329,6 +329,7 @@ CONFIG_DM_INIT=y
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
CONFIG_DM_BOW=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_WIREGUARD=y
@@ -553,7 +554,7 @@ CONFIG_DEVFREQ_GOV_PASSIVE=y
CONFIG_PM_DEVFREQ_EVENT=y
CONFIG_IIO=y
CONFIG_IIO_BUFFER=y
CONFIG_IIO_TRIGGER=y
CONFIG_IIO_TRIGGERED_BUFFER=y
CONFIG_PWM=y
CONFIG_GENERIC_PHY=y
CONFIG_POWERCAP=y
@@ -581,6 +582,7 @@ CONFIG_QUOTA=y
CONFIG_QFMT_V2=y
CONFIG_FUSE_FS=y
CONFIG_VIRTIO_FS=y
CONFIG_FUSE_BPF=y
CONFIG_OVERLAY_FS=y
CONFIG_INCREMENTAL_FS=y
CONFIG_MSDOS_FS=y
@@ -593,6 +595,8 @@ CONFIG_PSTORE_CONSOLE=y
CONFIG_PSTORE_PMSG=y
CONFIG_PSTORE_RAM=y
CONFIG_EROFS_FS=y
CONFIG_EROFS_FS_PCPU_KTHREAD=y
CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_CODEPAGE_737=y
CONFIG_NLS_CODEPAGE_775=y

View File

@@ -25,7 +25,7 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
({ \
efi_virtmap_load(); \
__efi_fpsimd_begin(); \
spin_lock(&efi_rt_lock); \
raw_spin_lock(&efi_rt_lock); \
})
#define arch_efi_call_virt(p, f, args...) \
@@ -37,12 +37,12 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
#define arch_efi_call_virt_teardown() \
({ \
spin_unlock(&efi_rt_lock); \
raw_spin_unlock(&efi_rt_lock); \
__efi_fpsimd_end(); \
efi_virtmap_unload(); \
})
extern spinlock_t efi_rt_lock;
extern raw_spinlock_t efi_rt_lock;
efi_status_t __efi_rt_asm_wrapper(void *, const char *, ...);
#define ARCH_EFI_IRQ_FLAGS_MASK (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT)

View File

@@ -145,7 +145,7 @@ asmlinkage efi_status_t efi_handle_corrupted_x18(efi_status_t s, const char *f)
return s;
}
DEFINE_SPINLOCK(efi_rt_lock);
DEFINE_RAW_SPINLOCK(efi_rt_lock);
asmlinkage u64 *efi_rt_stack_top __ro_after_init;

View File

@@ -65,7 +65,6 @@ static int mte_dump_tag_range(struct coredump_params *cprm,
mte_save_page_tags(page_address(page), tags);
put_page(page);
if (!dump_emit(cprm, tags, MTE_PAGE_TAG_STORAGE)) {
mte_free_tag_storage(tags);
ret = 0;
break;
}
@@ -77,7 +76,7 @@ static int mte_dump_tag_range(struct coredump_params *cprm,
return ret;
}
Elf_Half elf_core_extra_phdrs(void)
Elf_Half elf_core_extra_phdrs(struct coredump_params *cprm)
{
struct vm_area_struct *vma;
int vma_count = 0;
@@ -112,7 +111,7 @@ int elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset)
return 1;
}
size_t elf_core_extra_data_size(void)
size_t elf_core_extra_data_size(struct coredump_params *cprm)
{
struct vm_area_struct *vma;
size_t data_size = 0;

View File

@@ -959,7 +959,7 @@ static enum pkvm_page_state hyp_get_page_state(kvm_pte_t pte)
if (!kvm_pte_valid(pte))
return PKVM_NOPAGE;
return pkvm_getstate(kvm_pgtable_stage2_pte_prot(pte));
return pkvm_getstate(kvm_pgtable_hyp_pte_prot(pte));
}
static int __hyp_check_page_state_range(u64 addr, u64 size,

View File

@@ -543,6 +543,7 @@ static int __kprobes do_page_fault(unsigned long far, unsigned int esr,
unsigned long addr = untagged_addr(far);
#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
struct vm_area_struct *vma;
struct vm_area_struct pvma;
unsigned long seq;
#endif
@@ -626,17 +627,17 @@ static int __kprobes do_page_fault(unsigned long far, unsigned int esr,
count_vm_spf_event(SPF_ABORT_NO_SPECULATE);
goto spf_abort;
}
pvma = *vma;
if (!mmap_seq_read_check(mm, seq, SPF_ABORT_VMA_COPY)) {
put_vma(vma);
goto spf_abort;
}
if (!(vma->vm_flags & vm_flags)) {
if (!(pvma.vm_flags & vm_flags)) {
put_vma(vma);
count_vm_spf_event(SPF_ABORT_ACCESS_ERROR);
goto spf_abort;
}
fault = do_handle_mm_fault(vma, addr & PAGE_MASK,
fault = do_handle_mm_fault(&pvma, addr & PAGE_MASK,
mm_flags | FAULT_FLAG_SPECULATIVE, seq, regs);
put_vma(vma);

View File

@@ -7,7 +7,7 @@
#include <asm/elf.h>
Elf64_Half elf_core_extra_phdrs(void)
Elf64_Half elf_core_extra_phdrs(struct coredump_params *cprm)
{
return GATE_EHDR->e_phnum;
}
@@ -60,7 +60,7 @@ int elf_core_write_extra_data(struct coredump_params *cprm)
return 1;
}
size_t elf_core_extra_data_size(void)
size_t elf_core_extra_data_size(struct coredump_params *cprm)
{
const struct elf_phdr *const gate_phdrs =
(const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff);

View File

@@ -395,6 +395,7 @@ static int ___do_page_fault(struct pt_regs *regs, unsigned long address,
vm_fault_t fault, major = 0;
bool kprobe_fault = kprobe_page_fault(regs, 11);
#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
struct vm_area_struct pvma;
unsigned long seq;
#endif
@@ -477,25 +478,25 @@ static int ___do_page_fault(struct pt_regs *regs, unsigned long address,
count_vm_spf_event(SPF_ABORT_NO_SPECULATE);
goto spf_abort;
}
pvma = *vma;
if (!mmap_seq_read_check(mm, seq, SPF_ABORT_VMA_COPY)) {
put_vma(vma);
goto spf_abort;
}
#ifdef CONFIG_PPC_MEM_KEYS
if (unlikely(access_pkey_error(is_write, is_exec,
(error_code & DSISR_KEYFAULT), vma))) {
(error_code & DSISR_KEYFAULT), &pvma))) {
put_vma(vma);
count_vm_spf_event(SPF_ABORT_ACCESS_ERROR);
goto spf_abort;
}
#endif /* CONFIG_PPC_MEM_KEYS */
if (unlikely(access_error(is_write, is_exec, vma))) {
if (unlikely(access_error(is_write, is_exec, &pvma))) {
put_vma(vma);
count_vm_spf_event(SPF_ABORT_ACCESS_ERROR);
goto spf_abort;
}
fault = do_handle_mm_fault(vma, address,
fault = do_handle_mm_fault(&pvma, address,
flags | FAULT_FLAG_SPECULATIVE, seq, regs);
put_vma(vma);
major |= fault & VM_FAULT_MAJOR;

View File

@@ -39,8 +39,10 @@ CONFIG_NAMESPACES=y
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
CONFIG_BOOT_CONFIG=y
# CONFIG_UID16 is not set
# CONFIG_SYSFS_SYSCALL is not set
# CONFIG_FHANDLE is not set
# CONFIG_PCSPKR_PLATFORM is not set
CONFIG_KALLSYMS_ALL=y
CONFIG_USERFAULTFD=y
# CONFIG_RSEQ is not set
@@ -58,6 +60,9 @@ CONFIG_PARAVIRT=y
CONFIG_PARAVIRT_TIME_ACCOUNTING=y
CONFIG_NR_CPUS=32
# CONFIG_X86_MCE is not set
# CONFIG_MICROCODE is not set
# CONFIG_X86_5LEVEL is not set
# CONFIG_MTRR_SANITIZER is not set
CONFIG_EFI=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="stack_depot_disable=on cgroup_disable=pressure"
@@ -65,6 +70,11 @@ CONFIG_HIBERNATION=y
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_LIMIT=0
# CONFIG_PM_WAKELOCKS_GC is not set
# CONFIG_ACPI_AC is not set
# CONFIG_ACPI_BATTERY is not set
# CONFIG_ACPI_FAN is not set
# CONFIG_ACPI_THERMAL is not set
# CONFIG_X86_PM_TIMER is not set
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_TIMES=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
@@ -298,6 +308,7 @@ CONFIG_DM_INIT=y
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
CONFIG_DM_BOW=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_WIREGUARD=y
@@ -354,6 +365,7 @@ CONFIG_SERIAL_SAMSUNG=y
CONFIG_SERIAL_SAMSUNG_CONSOLE=y
CONFIG_SERIAL_DEV_BUS=y
CONFIG_HW_RANDOM=y
# CONFIG_HW_RANDOM_VIA is not set
# CONFIG_DEVMEM is not set
# CONFIG_DEVPORT is not set
CONFIG_HPET=y
@@ -471,6 +483,7 @@ CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_TRANSIENT=y
CONFIG_EDAC=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_HCTOSYS is not set
CONFIG_DMABUF_HEAPS=y
CONFIG_DMABUF_SYSFS_STATS=y
CONFIG_DMABUF_HEAPS_DEFERRED_FREE=y
@@ -487,7 +500,7 @@ CONFIG_RPMSG_CHAR=y
CONFIG_PM_DEVFREQ_EVENT=y
CONFIG_IIO=y
CONFIG_IIO_BUFFER=y
CONFIG_IIO_TRIGGER=y
CONFIG_IIO_TRIGGERED_BUFFER=y
CONFIG_POWERCAP=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
@@ -512,6 +525,7 @@ CONFIG_QUOTA=y
CONFIG_QFMT_V2=y
CONFIG_FUSE_FS=y
CONFIG_VIRTIO_FS=y
CONFIG_FUSE_BPF=y
CONFIG_OVERLAY_FS=y
CONFIG_INCREMENTAL_FS=y
CONFIG_MSDOS_FS=y
@@ -525,6 +539,8 @@ CONFIG_PSTORE_CONSOLE=y
CONFIG_PSTORE_PMSG=y
CONFIG_PSTORE_RAM=y
CONFIG_EROFS_FS=y
CONFIG_EROFS_FS_PCPU_KTHREAD=y
CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_CODEPAGE_737=y
CONFIG_NLS_CODEPAGE_775=y

View File

@@ -1227,6 +1227,7 @@ void do_user_addr_fault(struct pt_regs *regs,
vm_fault_t fault;
unsigned int flags = FAULT_FLAG_DEFAULT;
#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
struct vm_area_struct pvma;
unsigned long seq;
#endif
@@ -1351,17 +1352,17 @@ void do_user_addr_fault(struct pt_regs *regs,
count_vm_spf_event(SPF_ABORT_NO_SPECULATE);
goto spf_abort;
}
pvma = *vma;
if (!mmap_seq_read_check(mm, seq, SPF_ABORT_VMA_COPY)) {
put_vma(vma);
goto spf_abort;
}
if (unlikely(access_error(error_code, vma))) {
if (unlikely(access_error(error_code, &pvma))) {
put_vma(vma);
count_vm_spf_event(SPF_ABORT_ACCESS_ERROR);
goto spf_abort;
}
fault = do_handle_mm_fault(vma, address,
fault = do_handle_mm_fault(&pvma, address,
flags | FAULT_FLAG_SPECULATIVE, seq, regs);
put_vma(vma);

View File

@@ -7,7 +7,7 @@
#include <asm/elf.h>
Elf32_Half elf_core_extra_phdrs(void)
Elf32_Half elf_core_extra_phdrs(struct coredump_params *cprm)
{
return vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0;
}
@@ -60,7 +60,7 @@ int elf_core_write_extra_data(struct coredump_params *cprm)
return 1;
}
size_t elf_core_extra_data_size(void)
size_t elf_core_extra_data_size(struct coredump_params *cprm)
{
if ( vsyscall_ehdr ) {
const struct elfhdr *const ehdrp =

View File

@@ -37,6 +37,8 @@ android/abi_gki_aarch64_oplus
android/abi_gki_aarch64_amlogic
android/abi_gki_aarch64_sunxi
android/abi_gki_aarch64_pasa
android/abi_gki_aarch64_zeku
android/abi_gki_aarch64_lenovo
"
FILES="${FILES}

View File

@@ -6,7 +6,7 @@ LTO=none
function update_kasan_config() {
${KERNEL_DIR}/scripts/config --file ${OUT_DIR}/.config \
-e CONFIG_KASAN \
-e CONFIG_KASAN_INLINE \
-e CONFIG_KASAN_PANIC_ON_WARN \
-e CONFIG_KCOV \
-e CONFIG_PANIC_ON_WARN_DEFAULT_ENABLE \
-d CONFIG_RANDOMIZE_BASE \

File diff suppressed because it is too large Load Diff

View File

@@ -3049,11 +3049,11 @@ static void binder_transaction(struct binder_proc *proc,
int t_debug_id = atomic_inc_return(&binder_last_id);
char *secctx = NULL;
u32 secctx_sz = 0;
bool is_nested = false;
struct list_head sgc_head;
struct list_head pf_head;
const void __user *user_buffer = (const void __user *)
(uintptr_t)tr->data.ptr.buffer;
bool is_nested = false;
INIT_LIST_HEAD(&sgc_head);
INIT_LIST_HEAD(&pf_head);
@@ -3253,7 +3253,6 @@ static void binder_transaction(struct binder_proc *proc,
if (target_thread)
e->to_thread = target_thread->pid;
e->to_proc = target_proc->pid;
trace_android_rvh_binder_transaction(target_proc, proc, thread, tr);
/* TODO: reuse incoming transaction for reply */
t = kzalloc(sizeof(*t), GFP_KERNEL);

View File

@@ -109,6 +109,7 @@
#include <trace/hooks/dm.h>
#include <trace/hooks/direct_io.h>
#include <trace/hooks/loop.h>
#include <trace/hooks/psi.h>
/*
* Export tracepoints that act as a bare tracehook (ie: have no trace event
* associated with them) to allow external modules to probe them.
@@ -141,10 +142,16 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_process_killed);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_killed_process);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rtmutex_wait_start);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rtmutex_wait_finish);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mutex_opt_spin_start);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mutex_opt_spin_finish);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mutex_can_spin_on_owner);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_read_wait_start);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_read_wait_finish);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_write_wait_start);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_write_wait_finish);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_opt_spin_start);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_opt_spin_finish);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_can_spin_on_owner);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_sched_show_task);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_cpu_idle_enter);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_cpu_idle_exit);
@@ -227,7 +234,6 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_cpuidle_psci_enter);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_cpuidle_psci_exit);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_cgroup_force_kthread_migration);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_wait_for_work);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_binder_transaction);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_proc_transaction_entry);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_select_worklist_ilocked);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_proc_transaction_finish);
@@ -307,6 +313,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_thermal_unregister);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rproc_recovery_set);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_disable_thermal_cooling_stats);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_enable_thermal_power_throttle);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_modify_thermal_throttle_update);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_init);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_wake);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rwsem_write_finished);
@@ -417,6 +424,8 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_dm_update_clone_bio);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_ctl_dirty_rate);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_direct_io_update_bio);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_loop_prepare_cmd);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_psi_event);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_psi_group);
/*
* For type visibility
*/

View File

@@ -495,7 +495,8 @@ EXPORT_SYMBOL_GPL(regcache_drop_region);
void regcache_cache_only(struct regmap *map, bool enable)
{
map->lock(map->lock_arg);
WARN_ON(map->cache_bypass && enable);
WARN_ON(map->cache_type != REGCACHE_NONE &&
map->cache_bypass && enable);
map->cache_only = enable;
trace_regmap_cache_only(map, enable);
map->unlock(map->lock_arg);

View File

@@ -2191,35 +2191,44 @@ static blk_status_t loop_queue_rq(struct blk_mq_hw_ctx *hctx,
static void loop_handle_cmd(struct loop_cmd *cmd)
{
struct cgroup_subsys_state *cmd_blkcg_css = cmd->blkcg_css;
struct cgroup_subsys_state *cmd_memcg_css = cmd->memcg_css;
struct request *rq = blk_mq_rq_from_pdu(cmd);
const bool write = op_is_write(req_op(rq));
struct loop_device *lo = rq->q->queuedata;
int ret = 0;
struct mem_cgroup *old_memcg = NULL;
const bool use_aio = cmd->use_aio;
if (write && (lo->lo_flags & LO_FLAGS_READ_ONLY)) {
ret = -EIO;
goto failed;
}
if (cmd->blkcg_css)
kthread_associate_blkcg(cmd->blkcg_css);
if (cmd->memcg_css)
if (cmd_blkcg_css)
kthread_associate_blkcg(cmd_blkcg_css);
if (cmd_memcg_css)
old_memcg = set_active_memcg(
mem_cgroup_from_css(cmd->memcg_css));
mem_cgroup_from_css(cmd_memcg_css));
/*
* do_req_filebacked() may call blk_mq_complete_request() synchronously
* or asynchronously if using aio. Hence, do not touch 'cmd' after
* do_req_filebacked() has returned unless we are sure that 'cmd' has
* not yet been completed.
*/
ret = do_req_filebacked(lo, rq);
if (cmd->blkcg_css)
if (cmd_blkcg_css)
kthread_associate_blkcg(NULL);
if (cmd->memcg_css) {
if (cmd_memcg_css) {
set_active_memcg(old_memcg);
css_put(cmd->memcg_css);
css_put(cmd_memcg_css);
}
failed:
/* complete non-aio request */
if (!cmd->use_aio || ret) {
if (!use_aio || ret) {
if (ret == -EOPNOTSUPP)
cmd->ret = ret;
else

View File

@@ -18,13 +18,20 @@ static DEFINE_IDA(rng_index_ida);
struct virtrng_info {
struct hwrng hwrng;
struct virtqueue *vq;
struct completion have_data;
char name[25];
unsigned int data_avail;
int index;
bool busy;
bool hwrng_register_done;
bool hwrng_removed;
/* data transfer */
struct completion have_data;
unsigned int data_avail;
/* minimal size returned by rng_buffer_size() */
#if SMP_CACHE_BYTES < 32
u8 data[32];
#else
u8 data[SMP_CACHE_BYTES];
#endif
};
static void random_recv_done(struct virtqueue *vq)
@@ -39,14 +46,14 @@ static void random_recv_done(struct virtqueue *vq)
}
/* The host will fill any buffer we give it with sweet, sweet randomness. */
static void register_buffer(struct virtrng_info *vi, u8 *buf, size_t size)
static void register_buffer(struct virtrng_info *vi)
{
struct scatterlist sg;
sg_init_one(&sg, buf, size);
sg_init_one(&sg, vi->data, sizeof(vi->data));
/* There should always be room for one buffer. */
virtqueue_add_inbuf(vi->vq, &sg, 1, buf, GFP_KERNEL);
virtqueue_add_inbuf(vi->vq, &sg, 1, vi->data, GFP_KERNEL);
virtqueue_kick(vi->vq);
}
@@ -55,6 +62,8 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
{
int ret;
struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
unsigned int chunk;
size_t read;
if (vi->hwrng_removed)
return -ENODEV;
@@ -62,19 +71,33 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
if (!vi->busy) {
vi->busy = true;
reinit_completion(&vi->have_data);
register_buffer(vi, buf, size);
register_buffer(vi);
}
if (!wait)
return 0;
ret = wait_for_completion_killable(&vi->have_data);
if (ret < 0)
return ret;
read = 0;
while (size != 0) {
ret = wait_for_completion_killable(&vi->have_data);
if (ret < 0)
return ret;
chunk = min_t(unsigned int, size, vi->data_avail);
memcpy(buf + read, vi->data, chunk);
read += chunk;
size -= chunk;
vi->data_avail = 0;
if (size != 0) {
reinit_completion(&vi->have_data);
register_buffer(vi);
}
}
vi->busy = false;
return vi->data_avail;
return read;
}
static void virtio_cleanup(struct hwrng *rng)

View File

@@ -69,10 +69,12 @@ static int __psci_enter_domain_idle_state(struct cpuidle_device *dev,
if (ret)
return -1;
trace_android_vh_cpuidle_psci_enter(dev, s2idle);
/* Do runtime PM to manage a hierarchical CPU toplogy. */
rcu_irq_enter_irqson();
trace_android_vh_cpuidle_psci_enter(dev, s2idle);
if (s2idle)
dev_pm_genpd_suspend(pd_dev);
else
@@ -90,10 +92,11 @@ static int __psci_enter_domain_idle_state(struct cpuidle_device *dev,
dev_pm_genpd_resume(pd_dev);
else
pm_runtime_get_sync(pd_dev);
rcu_irq_exit_irqson();
trace_android_vh_cpuidle_psci_exit(dev, s2idle);
rcu_irq_exit_irqson();
cpu_pm_exit();
/* Clear the domain state to start fresh when back from idle. */

View File

@@ -318,9 +318,9 @@ static int system_heap_zero_buffer(struct system_heap_buffer *buffer)
for_each_sgtable_page(sgt, &piter, 0) {
p = sg_page_iter_page(&piter);
vaddr = kmap_atomic(p);
vaddr = kmap_local_page(p);
memset(vaddr, 0, PAGE_SIZE);
kunmap_atomic(vaddr);
kunmap_local(vaddr);
}
return ret;

View File

@@ -1119,6 +1119,16 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
return;
}
goto unknown;
case HID_UP_CAMERA:
switch (usage->hid & HID_USAGE) {
case 0x020:
map_key_clear(KEY_CAMERA_FOCUS); break;
case 0x021:
map_key_clear(KEY_CAMERA); break;
default:
goto ignore;
}
break;
case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */
set_bit(EV_REP, input->evbit);

View File

@@ -221,13 +221,23 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
const struct iommu_ops *ops = dev->bus->iommu_ops;
struct iommu_device *iommu_dev;
struct iommu_group *group;
static DEFINE_MUTEX(iommu_probe_device_lock);
int ret;
if (!ops)
return -ENODEV;
if (!dev_iommu_get(dev))
return -ENOMEM;
/*
* Serialise to avoid races between IOMMU drivers registering in
* parallel and/or the "replay" calls from ACPI/OF code via client
* driver probe. Once the latter have been cleaned up we should
* probably be able to use device_lock() here to minimise the scope,
* but for now enforcing a simple global ordering is fine.
*/
mutex_lock(&iommu_probe_device_lock);
if (!dev_iommu_get(dev)) {
ret = -ENOMEM;
goto err_unlock;
}
if (!try_module_get(ops->owner)) {
ret = -EINVAL;
@@ -247,11 +257,14 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
ret = PTR_ERR(group);
goto out_release;
}
iommu_group_put(group);
mutex_lock(&group->mutex);
if (group_list && !group->default_domain && list_empty(&group->entry))
list_add_tail(&group->entry, group_list);
mutex_unlock(&group->mutex);
iommu_group_put(group);
mutex_unlock(&iommu_probe_device_lock);
iommu_device_link(iommu_dev, dev);
return 0;
@@ -265,6 +278,9 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
err_free:
dev_iommu_free(dev);
err_unlock:
mutex_unlock(&iommu_probe_device_lock);
return ret;
}
@@ -1807,11 +1823,11 @@ int bus_iommu_probe(struct bus_type *bus)
return ret;
list_for_each_entry_safe(group, next, &group_list, entry) {
mutex_lock(&group->mutex);
/* Remove item from the list */
list_del_init(&group->entry);
mutex_lock(&group->mutex);
/* Try to allocate default domain */
probe_alloc_default_domain(bus, group);

View File

@@ -663,14 +663,17 @@ config DM_ZONED
If unsure, say N.
config DM_AUDIT
bool "DM audit events"
depends on AUDIT
config DM_BOW
tristate "Backup block device"
depends on BLK_DEV_DM
select DM_BUFIO
help
Generate audit events for device-mapper.
This device-mapper target takes a device and keeps a log of all
changes using free blocks identified by issuing a trim command.
This can then be restored by running a command line utility,
or committed by simply replacing the target.
Enables audit logging of several security relevant events in the
particular device-mapper targets, especially the integrity target.
If unsure, say N.
config DM_USER
tristate "Block device in userspace"

View File

@@ -84,6 +84,7 @@ obj-$(CONFIG_DM_LOG_WRITES) += dm-log-writes.o
obj-$(CONFIG_DM_INTEGRITY) += dm-integrity.o
obj-$(CONFIG_DM_ZONED) += dm-zoned.o
obj-$(CONFIG_DM_WRITECACHE) += dm-writecache.o
obj-$(CONFIG_DM_BOW) += dm-bow.o
obj-$(CONFIG_DM_USER) += dm-user.o
ifeq ($(CONFIG_DM_INIT),y)

1309
drivers/md/dm-bow.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1280,8 +1280,16 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
goto bad;
}
/* WQ_UNBOUND greatly improves performance when running on ramdisk */
v->verify_wq = alloc_workqueue("kverityd", WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM | WQ_UNBOUND, num_online_cpus());
/*
* Using WQ_HIGHPRI improves throughput and completion latency by
* reducing wait times when reading from a dm-verity device.
*
* Also as required for the "try_verify_in_tasklet" feature: WQ_HIGHPRI
* allows verify_wq to preempt softirq since verification in tasklet
* will fall-back to using it for error handling (or if the bufio cache
* doesn't have required hashes).
*/
v->verify_wq = alloc_workqueue("kverityd", WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
if (!v->verify_wq) {
ti->error = "Cannot allocate workqueue";
r = -ENOMEM;

View File

@@ -1119,7 +1119,7 @@ void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq,
NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT);
mutex_lock(&vif->wdev.mtx);
cfg80211_ch_switch_notify(vif->ndev, &chandef, 0);
cfg80211_ch_switch_notify(vif->ndev, &chandef, 0, 0);
mutex_unlock(&vif->wdev.mtx);
}

View File

@@ -6013,7 +6013,7 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
brcmf_dbg(CONN, "Report roaming result\n");
if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X && profile->is_ft) {
cfg80211_port_authorized(ndev, profile->bssid, GFP_KERNEL);
cfg80211_port_authorized(ndev, profile->bssid, NULL, 0, GFP_KERNEL);
brcmf_dbg(CONN, "Report port authorized\n");
}

View File

@@ -304,6 +304,6 @@ void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work)
mwifiex_dbg(priv->adapter, MSG,
"indicating channel switch completion to kernel\n");
mutex_lock(&priv->wdev.mtx);
cfg80211_ch_switch_notify(priv->netdev, &priv->dfs_chandef, 0);
cfg80211_ch_switch_notify(priv->netdev, &priv->dfs_chandef, 0, 0);
mutex_unlock(&priv->wdev.mtx);
}

View File

@@ -478,7 +478,7 @@ qtnf_event_handle_freq_change(struct qtnf_wmac *mac,
continue;
mutex_lock(&vif->wdev.mtx);
cfg80211_ch_switch_notify(vif->netdev, &chandef, 0);
cfg80211_ch_switch_notify(vif->netdev, &chandef, 0, 0);
mutex_unlock(&vif->wdev.mtx);
}
@@ -662,6 +662,7 @@ qtnf_event_handle_update_owe(struct qtnf_vif *vif,
memcpy(ie, owe_ev->ies, ie_len);
owe_info.ie_len = ie_len;
owe_info.ie = ie;
owe_info.assoc_link_id = -1;
pr_info("%s: external OWE processing: peer=%pM\n",
vif->netdev->name, owe_ev->peer);

View File

@@ -26,7 +26,6 @@
#include <linux/serial_core.h>
#include <linux/sysfs.h>
#include <linux/random.h>
#include <linux/kmemleak.h>
#include <asm/setup.h> /* for COMMAND_LINE_SIZE */
#include <asm/page.h>
@@ -525,12 +524,9 @@ static int __init __reserved_mem_reserve_reg(unsigned long node,
size = dt_mem_next_cell(dt_root_size_cells, &prop);
if (size &&
early_init_dt_reserve_memory_arch(base, size, nomap) == 0) {
early_init_dt_reserve_memory_arch(base, size, nomap) == 0)
pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %lu MiB\n",
uname, &base, (unsigned long)(size / SZ_1M));
if (!nomap)
kmemleak_alloc_phys(base, size, 0, 0);
}
else
pr_info("Reserved memory: failed to reserve memory for node '%s': base %pa, size %lu MiB\n",
uname, &base, (unsigned long)(size / SZ_1M));

View File

@@ -36,7 +36,7 @@
#define CMN_CI_CHILD_COUNT GENMASK_ULL(15, 0)
#define CMN_CI_CHILD_PTR_OFFSET GENMASK_ULL(31, 16)
#define CMN_CHILD_NODE_ADDR GENMASK(27, 0)
#define CMN_CHILD_NODE_ADDR GENMASK(29, 0)
#define CMN_CHILD_NODE_EXTERNAL BIT(31)
#define CMN_MAX_DIMENSION 8
@@ -71,9 +71,11 @@
#define CMN_DTM_WPn(n) (0x1A0 + (n) * 0x18)
#define CMN_DTM_WPn_CONFIG(n) (CMN_DTM_WPn(n) + 0x00)
#define CMN_DTM_WPn_CONFIG_WP_DEV_SEL2 GENMASK_ULL(18,17)
#define CMN_DTM_WPn_CONFIG_WP_COMBINE BIT(6)
#define CMN_DTM_WPn_CONFIG_WP_EXCLUSIVE BIT(5)
#define CMN_DTM_WPn_CONFIG_WP_GRP BIT(4)
#define CMN_DTM_WPn_CONFIG_WP_COMBINE BIT(9)
#define CMN_DTM_WPn_CONFIG_WP_EXCLUSIVE BIT(8)
#define CMN600_WPn_CONFIG_WP_COMBINE BIT(6)
#define CMN600_WPn_CONFIG_WP_EXCLUSIVE BIT(5)
#define CMN_DTM_WPn_CONFIG_WP_GRP GENMASK_ULL(5, 4)
#define CMN_DTM_WPn_CONFIG_WP_CHN_SEL GENMASK_ULL(3, 1)
#define CMN_DTM_WPn_CONFIG_WP_DEV_SEL BIT(0)
#define CMN_DTM_WPn_VAL(n) (CMN_DTM_WPn(n) + 0x08)
@@ -155,6 +157,7 @@
#define CMN_CONFIG_WP_COMBINE GENMASK_ULL(27, 24)
#define CMN_CONFIG_WP_DEV_SEL GENMASK_ULL(50, 48)
#define CMN_CONFIG_WP_CHN_SEL GENMASK_ULL(55, 51)
/* Note that we don't yet support the tertiary match group on newer IPs */
#define CMN_CONFIG_WP_GRP BIT_ULL(56)
#define CMN_CONFIG_WP_EXCLUSIVE BIT_ULL(57)
#define CMN_CONFIG1_WP_VAL GENMASK_ULL(63, 0)
@@ -595,6 +598,9 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj,
if ((intf & 4) && !(cmn->ports_used & BIT(intf & 3)))
return 0;
if (chan == 4 && cmn->model == CMN600)
return 0;
if ((chan == 5 && cmn->rsp_vc_num < 2) ||
(chan == 6 && cmn->dat_vc_num < 2))
return 0;
@@ -905,15 +911,18 @@ static u32 arm_cmn_wp_config(struct perf_event *event)
u32 grp = CMN_EVENT_WP_GRP(event);
u32 exc = CMN_EVENT_WP_EXCLUSIVE(event);
u32 combine = CMN_EVENT_WP_COMBINE(event);
bool is_cmn600 = to_cmn(event->pmu)->model == CMN600;
config = FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_DEV_SEL, dev) |
FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_CHN_SEL, chn) |
FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_GRP, grp) |
FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_EXCLUSIVE, exc) |
FIELD_PREP(CMN_DTM_WPn_CONFIG_WP_DEV_SEL2, dev >> 1);
if (exc)
config |= is_cmn600 ? CMN600_WPn_CONFIG_WP_EXCLUSIVE :
CMN_DTM_WPn_CONFIG_WP_EXCLUSIVE;
if (combine && !grp)
config |= CMN_DTM_WPn_CONFIG_WP_COMBINE;
config |= is_cmn600 ? CMN600_WPn_CONFIG_WP_COMBINE :
CMN_DTM_WPn_CONFIG_WP_COMBINE;
return config;
}
@@ -1242,7 +1251,6 @@ static int arm_cmn_event_init(struct perf_event *event)
hw->dn++;
continue;
}
hw->dtcs_used |= arm_cmn_node_to_xp(cmn, dn)->dtc;
hw->num_dns++;
if (bynodeid)
break;
@@ -1255,6 +1263,12 @@ static int arm_cmn_event_init(struct perf_event *event)
nodeid, nid.x, nid.y, nid.port, nid.dev, type);
return -EINVAL;
}
/*
* Keep assuming non-cycles events count in all DTC domains; turns out
* it's hard to make a worthwhile optimisation around this, short of
* going all-in with domain-local counter allocation as well.
*/
hw->dtcs_used = (1U << cmn->num_dtcs) - 1;
return arm_cmn_validate_group(cmn, event);
}

View File

@@ -1548,10 +1548,16 @@ MODULE_DEVICE_TABLE(acpi, ufs_qcom_acpi_match);
#endif
static const struct dev_pm_ops ufs_qcom_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(ufshcd_system_suspend, ufshcd_system_resume)
SET_RUNTIME_PM_OPS(ufshcd_runtime_suspend, ufshcd_runtime_resume, NULL)
.prepare = ufshcd_suspend_prepare,
.complete = ufshcd_resume_complete,
#ifdef CONFIG_PM_SLEEP
.suspend = ufshcd_system_suspend,
.resume = ufshcd_system_resume,
.freeze = ufshcd_system_freeze,
.restore = ufshcd_system_restore,
.thaw = ufshcd_system_thaw,
#endif
};
static struct platform_driver ufs_qcom_pltform = {

View File

@@ -7872,7 +7872,7 @@ static int ufshcd_quirk_tune_host_pa_tactivate(struct ufs_hba *hba)
peer_pa_tactivate_us = peer_pa_tactivate *
gran_to_us_table[peer_granularity - 1];
if (pa_tactivate_us > peer_pa_tactivate_us) {
if (pa_tactivate_us >= peer_pa_tactivate_us) {
u32 new_peer_pa_tactivate;
new_peer_pa_tactivate = pa_tactivate_us /
@@ -8716,9 +8716,11 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
for (retries = 3; retries > 0; --retries) {
ret = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, &sshdr,
HZ, 0, 0, RQF_PM, NULL);
if (!scsi_status_is_check_condition(ret) ||
!scsi_sense_valid(&sshdr) ||
sshdr.sense_key != UNIT_ATTENTION)
/*
* scsi_execute() only returns a negative value if the request
* queue is dying.
*/
if (ret <= 0)
break;
}
if (ret) {
@@ -9499,6 +9501,56 @@ void ufshcd_remove(struct ufs_hba *hba)
}
EXPORT_SYMBOL_GPL(ufshcd_remove);
#ifdef CONFIG_PM_SLEEP
int ufshcd_system_freeze(struct device *dev)
{
return ufshcd_system_suspend(dev);
}
EXPORT_SYMBOL_GPL(ufshcd_system_freeze);
int ufshcd_system_restore(struct device *dev)
{
struct ufs_hba *hba = dev_get_drvdata(dev);
int ret;
ret = ufshcd_system_resume(dev);
if (ret)
return ret;
/* Configure UTRL and UTMRL base address registers */
ufshcd_writel(hba, lower_32_bits(hba->utrdl_dma_addr),
REG_UTP_TRANSFER_REQ_LIST_BASE_L);
ufshcd_writel(hba, upper_32_bits(hba->utrdl_dma_addr),
REG_UTP_TRANSFER_REQ_LIST_BASE_H);
ufshcd_writel(hba, lower_32_bits(hba->utmrdl_dma_addr),
REG_UTP_TASK_REQ_LIST_BASE_L);
ufshcd_writel(hba, upper_32_bits(hba->utmrdl_dma_addr),
REG_UTP_TASK_REQ_LIST_BASE_H);
/*
* Make sure that UTRL and UTMRL base address registers
* are updated with the latest queue addresses. Only after
* updating these addresses, we can queue the new commands.
*/
mb();
/* Resuming from hibernate, assume that link was OFF */
ufshcd_set_link_off(hba);
return 0;
}
EXPORT_SYMBOL_GPL(ufshcd_system_restore);
int ufshcd_system_thaw(struct device *dev)
{
return ufshcd_system_resume(dev);
}
EXPORT_SYMBOL_GPL(ufshcd_system_thaw);
#endif /* CONFIG_PM_SLEEP */
/**
* ufshcd_dealloc_host - deallocate Host Bus Adapter (HBA)
* @hba: pointer to Host Bus Adapter (HBA)

View File

@@ -1150,8 +1150,12 @@ extern int ufshcd_runtime_resume(struct device *dev);
#ifdef CONFIG_PM_SLEEP
extern int ufshcd_system_suspend(struct device *dev);
extern int ufshcd_system_resume(struct device *dev);
extern int ufshcd_system_freeze(struct device *dev);
extern int ufshcd_system_thaw(struct device *dev);
extern int ufshcd_system_restore(struct device *dev);
#endif
extern int ufshcd_shutdown(struct ufs_hba *hba);
extern int ufshcd_dme_configure_adapt(struct ufs_hba *hba,
int agreed_gear,
int adapt_val);

View File

@@ -60,6 +60,7 @@ struct time_in_idle {
* @cdev: thermal_cooling_device pointer to keep track of the
* registered cooling device.
* @policy: cpufreq policy.
* @cooling_ops: cpufreq callbacks to thermal cooling device ops
* @idle_time: idle time stats
* @qos_req: PM QoS contraint to apply
*
@@ -72,6 +73,7 @@ struct cpufreq_cooling_device {
unsigned int max_level;
struct em_perf_domain *em;
struct cpufreq_policy *policy;
struct thermal_cooling_device_ops cooling_ops;
#ifndef CONFIG_SMP
struct time_in_idle *idle_time;
#endif
@@ -496,14 +498,6 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev,
return ret;
}
/* Bind cpufreq callbacks to thermal cooling device ops */
static struct thermal_cooling_device_ops cpufreq_cooling_ops = {
.get_max_state = cpufreq_get_max_state,
.get_cur_state = cpufreq_get_cur_state,
.set_cur_state = cpufreq_set_cur_state,
};
/**
* __cpufreq_cooling_register - helper function to create cpufreq cooling device
* @np: a valid struct device_node to the cooling device device tree node
@@ -565,7 +559,10 @@ __cpufreq_cooling_register(struct device_node *np,
/* max_level is an index, not a counter */
cpufreq_cdev->max_level = i - 1;
cooling_ops = &cpufreq_cooling_ops;
cooling_ops = &cpufreq_cdev->cooling_ops;
cooling_ops->get_max_state = cpufreq_get_max_state;
cooling_ops->get_cur_state = cpufreq_get_cur_state;
cooling_ops->set_cur_state = cpufreq_set_cur_state;
#ifdef CONFIG_THERMAL_GOV_POWER_ALLOCATOR
if (em_is_sane(cpufreq_cdev, em)) {

View File

@@ -725,22 +725,22 @@ static int power_allocator_throttle(struct thermal_zone_device *tz, int trip)
return 0;
/*
* Enable or disable IPA control by temperature and user power budget.
* Control the IPA by user.
* About enable:
* true: enable IPA control when temperature >= swtich_on_temp.
* false: disable IPA control when temperature < switch_on_temp.
* true: enable IPA control.
* false: disable IPA control.
* About override:
* true: power budget is overridden by user power budget.
* false: power budget is not overridden, there's no other thermal
* requirement.
*/
trace_android_vh_enable_thermal_power_throttle(&enable, &override);
if (enable)
ret = tz->ops->get_trip_temp(tz, params->trip_switch_on,
ret = tz->ops->get_trip_temp(tz, params->trip_switch_on,
&switch_on_temp);
if (!enable || (!ret && (tz->temperature < switch_on_temp) &&
!override)) {
update = (tz->last_temperature >= switch_on_temp);
trace_android_vh_modify_thermal_throttle_update(tz, &update);
tz->passive = 0;
reset_pid_controller(params);
allow_maximum_power(tz, update);

View File

@@ -1709,6 +1709,7 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int
else if (!ret)
dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
dep->flags &= ~DWC3_EP_DELAY_STOP;
return ret;
}
@@ -2100,8 +2101,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
{
struct dwc3_gadget_ep_cmd_params params;
struct dwc3 *dwc = dep->dwc;
struct dwc3_request *req;
struct dwc3_request *tmp;
int ret;
if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
@@ -2150,8 +2149,8 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
dwc3_stop_active_transfer(dep, true, true);
list_for_each_entry_safe(req, tmp, &dep->started_list, list)
dwc3_gadget_move_cancelled_request(req, DWC3_REQUEST_STATUS_STALLED);
if (!list_empty(&dep->started_list))
dep->flags |= DWC3_EP_DELAY_START;
if (dep->flags & DWC3_EP_END_TRANSFER_PENDING ||
(dep->flags & DWC3_EP_DELAY_STOP)) {
@@ -2162,8 +2161,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
return 0;
}
dwc3_gadget_ep_cleanup_cancelled_requests(dep);
ret = dwc3_send_clear_stall_ep_cmd(dep);
if (ret) {
dev_err(dwc->dev, "failed to clear STALL on %s\n",
@@ -3705,8 +3702,10 @@ void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
if (dep->number <= 1 && dwc->ep0state != EP0_DATA_PHASE)
return;
if (interrupt && (dep->flags & DWC3_EP_DELAY_STOP))
return;
if (!(dep->flags & DWC3_EP_TRANSFER_STARTED) ||
(dep->flags & DWC3_EP_DELAY_STOP) ||
(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
return;
@@ -4210,15 +4209,8 @@ static void dwc3_gadget_interrupt(struct dwc3 *dwc,
break;
case DWC3_DEVICE_EVENT_SUSPEND:
/* It changed to be suspend event for version 2.30a and above */
if (!DWC3_VER_IS_PRIOR(DWC3, 230A)) {
/*
* Ignore suspend event until the gadget enters into
* USB_STATE_CONFIGURED state.
*/
if (dwc->gadget->state >= USB_STATE_CONFIGURED)
dwc3_gadget_suspend_interrupt(dwc,
event->event_info);
}
if (!DWC3_VER_IS_PRIOR(DWC3, 230A))
dwc3_gadget_suspend_interrupt(dwc, event->event_info);
break;
case DWC3_DEVICE_EVENT_SOF:
case DWC3_DEVICE_EVENT_ERRATIC_ERROR:

View File

@@ -2447,6 +2447,10 @@ void composite_resume(struct usb_gadget *gadget)
usb_gadget_clear_selfpowered(gadget);
usb_gadget_vbus_draw(gadget, maxpower);
} else {
maxpower = CONFIG_USB_GADGET_VBUS_DRAW;
maxpower = min(maxpower, 100U);
usb_gadget_vbus_draw(gadget, maxpower);
}
cdev->suspended = 0;

View File

@@ -16,7 +16,7 @@
#include <linux/usb/ch9.h>
#ifdef CONFIG_USB_CONFIGFS_F_ACC
extern int acc_ctrlrequest(struct usb_composite_dev *cdev,
extern int acc_ctrlrequest_composite(struct usb_composite_dev *cdev,
const struct usb_ctrlrequest *ctrl);
void acc_disconnect(void);
#endif
@@ -461,6 +461,12 @@ static int config_usb_cfg_link(
* from another gadget or a random directory.
* Also a function instance can only be linked once.
*/
if (gi->composite.gadget_driver.udc_name) {
ret = -EINVAL;
goto out;
}
list_for_each_entry(a_fi, &gi->available_func, cfs_list) {
if (a_fi == fi)
break;
@@ -1562,7 +1568,7 @@ static int android_setup(struct usb_gadget *gadget,
#ifdef CONFIG_USB_CONFIGFS_F_ACC
if (value < 0)
value = acc_ctrlrequest(cdev, c);
value = acc_ctrlrequest_composite(cdev, c);
#endif
if (value < 0)

View File

@@ -29,6 +29,7 @@
#include <linux/kthread.h>
#include <linux/freezer.h>
#include <linux/kref.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/file.h>
@@ -1076,11 +1077,32 @@ int acc_ctrlrequest(struct usb_composite_dev *cdev,
}
EXPORT_SYMBOL_GPL(acc_ctrlrequest);
int acc_ctrlrequest_composite(struct usb_composite_dev *cdev,
const struct usb_ctrlrequest *ctrl)
{
u16 w_length = le16_to_cpu(ctrl->wLength);
if (w_length > USB_COMP_EP0_BUFSIZ) {
if (ctrl->bRequestType & USB_DIR_IN) {
/* Cast away the const, we are going to overwrite on purpose. */
__le16 *temp = (__le16 *)&ctrl->wLength;
*temp = cpu_to_le16(USB_COMP_EP0_BUFSIZ);
w_length = USB_COMP_EP0_BUFSIZ;
} else {
return -EINVAL;
}
}
return acc_ctrlrequest(cdev, ctrl);
}
EXPORT_SYMBOL_GPL(acc_ctrlrequest_composite);
static int
__acc_function_bind(struct usb_configuration *c,
struct usb_function *f, bool configfs)
{
struct usb_composite_dev *cdev = c->cdev;
struct usb_string *us;
struct acc_dev *dev = func_to_dev(f);
int id;
int ret;
@@ -1088,13 +1110,11 @@ __acc_function_bind(struct usb_configuration *c,
DBG(cdev, "acc_function_bind dev: %p\n", dev);
if (configfs) {
if (acc_string_defs[INTERFACE_STRING_INDEX].id == 0) {
ret = usb_string_id(c->cdev);
if (ret < 0)
return ret;
acc_string_defs[INTERFACE_STRING_INDEX].id = ret;
acc_interface_desc.iInterface = ret;
}
us = usb_gstrings_attach(cdev, acc_strings, ARRAY_SIZE(acc_string_defs));
if (IS_ERR(us))
return PTR_ERR(us);
ret = us[INTERFACE_STRING_INDEX].id;
acc_interface_desc.iInterface = ret;
dev->cdev = c->cdev;
}
ret = hid_register_driver(&acc_hid_driver);

View File

@@ -1512,7 +1512,7 @@ UVCG_UNCOMPRESSED_ATTR(b_bits_per_pixel, bBitsPerPixel, 8);
UVCG_UNCOMPRESSED_ATTR(b_default_frame_index, bDefaultFrameIndex, 8);
UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, 8);
UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, 8);
UVCG_UNCOMPRESSED_ATTR_RO(bm_interface_flags, bmInterfaceFlags, 8);
UVCG_UNCOMPRESSED_ATTR_RO(bm_interlace_flags, bmInterlaceFlags, 8);
#undef UVCG_UNCOMPRESSED_ATTR
#undef UVCG_UNCOMPRESSED_ATTR_RO
@@ -1541,7 +1541,7 @@ static struct configfs_attribute *uvcg_uncompressed_attrs[] = {
&uvcg_uncompressed_attr_b_default_frame_index,
&uvcg_uncompressed_attr_b_aspect_ratio_x,
&uvcg_uncompressed_attr_b_aspect_ratio_y,
&uvcg_uncompressed_attr_bm_interface_flags,
&uvcg_uncompressed_attr_bm_interlace_flags,
&uvcg_uncompressed_attr_bma_controls,
NULL,
};
@@ -1574,7 +1574,7 @@ static struct config_group *uvcg_uncompressed_make(struct config_group *group,
h->desc.bDefaultFrameIndex = 1;
h->desc.bAspectRatioX = 0;
h->desc.bAspectRatioY = 0;
h->desc.bmInterfaceFlags = 0;
h->desc.bmInterlaceFlags = 0;
h->desc.bCopyProtect = 0;
INIT_LIST_HEAD(&h->fmt.frames);
@@ -1700,7 +1700,7 @@ UVCG_MJPEG_ATTR(b_default_frame_index, bDefaultFrameIndex, 8);
UVCG_MJPEG_ATTR_RO(bm_flags, bmFlags, 8);
UVCG_MJPEG_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, 8);
UVCG_MJPEG_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, 8);
UVCG_MJPEG_ATTR_RO(bm_interface_flags, bmInterfaceFlags, 8);
UVCG_MJPEG_ATTR_RO(bm_interlace_flags, bmInterlaceFlags, 8);
#undef UVCG_MJPEG_ATTR
#undef UVCG_MJPEG_ATTR_RO
@@ -1728,7 +1728,7 @@ static struct configfs_attribute *uvcg_mjpeg_attrs[] = {
&uvcg_mjpeg_attr_bm_flags,
&uvcg_mjpeg_attr_b_aspect_ratio_x,
&uvcg_mjpeg_attr_b_aspect_ratio_y,
&uvcg_mjpeg_attr_bm_interface_flags,
&uvcg_mjpeg_attr_bm_interlace_flags,
&uvcg_mjpeg_attr_bma_controls,
NULL,
};
@@ -1755,7 +1755,7 @@ static struct config_group *uvcg_mjpeg_make(struct config_group *group,
h->desc.bDefaultFrameIndex = 1;
h->desc.bAspectRatioX = 0;
h->desc.bAspectRatioY = 0;
h->desc.bmInterfaceFlags = 0;
h->desc.bmInterlaceFlags = 0;
h->desc.bCopyProtect = 0;
INIT_LIST_HEAD(&h->fmt.frames);

View File

@@ -171,7 +171,7 @@ static const struct uvc_format_uncompressed uvc_format_yuv = {
.bDefaultFrameIndex = 1,
.bAspectRatioX = 0,
.bAspectRatioY = 0,
.bmInterfaceFlags = 0,
.bmInterlaceFlags = 0,
.bCopyProtect = 0,
};
@@ -222,7 +222,7 @@ static const struct uvc_format_mjpeg uvc_format_mjpg = {
.bDefaultFrameIndex = 1,
.bAspectRatioX = 0,
.bAspectRatioY = 0,
.bmInterfaceFlags = 0,
.bmInterlaceFlags = 0,
.bCopyProtect = 0,
};

View File

@@ -2182,7 +2182,7 @@ static int elf_core_dump(struct coredump_params *cprm)
* The number of segs are recored into ELF header as 16bit value.
* Please check DEFAULT_MAX_MAP_COUNT definition when you modify here.
*/
segs = cprm->vma_count + elf_core_extra_phdrs();
segs = cprm->vma_count + elf_core_extra_phdrs(cprm);
/* for notes section */
segs++;
@@ -2222,7 +2222,7 @@ static int elf_core_dump(struct coredump_params *cprm)
dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
offset += cprm->vma_data_size;
offset += elf_core_extra_data_size();
offset += elf_core_extra_data_size(cprm);
e_shoff = offset;
if (e_phnum == PN_XNUM) {

View File

@@ -1509,7 +1509,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
tmp->next = thread_list;
thread_list = tmp;
segs = cprm->vma_count + elf_core_extra_phdrs();
segs = cprm->vma_count + elf_core_extra_phdrs(cprm);
/* for notes section */
segs++;
@@ -1555,7 +1555,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
offset += cprm->vma_data_size;
offset += elf_core_extra_data_size();
offset += elf_core_extra_data_size(cprm);
e_shoff = offset;
if (e_phnum == PN_XNUM) {

View File

@@ -98,3 +98,21 @@ config EROFS_FS_ZIP_LZMA
systems will be readable without selecting this option.
If unsure, say N.
config EROFS_FS_PCPU_KTHREAD
bool "EROFS per-cpu decompression kthread workers"
depends on EROFS_FS_ZIP
help
Saying Y here enables per-CPU kthread workers pool to carry out
async decompression for low latencies on some architectures.
If unsure, say N.
config EROFS_FS_PCPU_KTHREAD_HIPRI
bool "EROFS high priority per-CPU kthread workers"
depends on EROFS_FS_ZIP && EROFS_FS_PCPU_KTHREAD
help
This permits EROFS to configure per-CPU kthread workers to run
at higher priority.
If unsure, say N.

View File

@@ -6,7 +6,7 @@
#include "zdata.h"
#include "compress.h"
#include <linux/prefetch.h>
#include <linux/cpuhotplug.h>
#include <trace/events/erofs.h>
/*
@@ -117,24 +117,128 @@ typedef tagptr1_t compressed_page_t;
static struct workqueue_struct *z_erofs_workqueue __read_mostly;
void z_erofs_exit_zip_subsystem(void)
#ifdef CONFIG_EROFS_FS_PCPU_KTHREAD
static struct kthread_worker __rcu **z_erofs_pcpu_workers;
static void erofs_destroy_percpu_workers(void)
{
destroy_workqueue(z_erofs_workqueue);
z_erofs_destroy_pcluster_pool();
struct kthread_worker *worker;
unsigned int cpu;
for_each_possible_cpu(cpu) {
worker = rcu_dereference_protected(
z_erofs_pcpu_workers[cpu], 1);
rcu_assign_pointer(z_erofs_pcpu_workers[cpu], NULL);
if (worker)
kthread_destroy_worker(worker);
}
kfree(z_erofs_pcpu_workers);
}
static inline int z_erofs_init_workqueue(void)
static struct kthread_worker *erofs_init_percpu_worker(int cpu)
{
const unsigned int onlinecpus = num_possible_cpus();
struct kthread_worker *worker =
kthread_create_worker_on_cpu(cpu, 0, "erofs_worker/%u", cpu);
/*
* no need to spawn too many threads, limiting threads could minimum
* scheduling overhead, perhaps per-CPU threads should be better?
*/
z_erofs_workqueue = alloc_workqueue("erofs_unzipd",
WQ_UNBOUND | WQ_HIGHPRI,
onlinecpus + onlinecpus / 4);
return z_erofs_workqueue ? 0 : -ENOMEM;
if (IS_ERR(worker))
return worker;
if (IS_ENABLED(CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI))
sched_set_fifo_low(worker->task);
else
sched_set_normal(worker->task, 0);
return worker;
}
static int erofs_init_percpu_workers(void)
{
struct kthread_worker *worker;
unsigned int cpu;
z_erofs_pcpu_workers = kcalloc(num_possible_cpus(),
sizeof(struct kthread_worker *), GFP_ATOMIC);
if (!z_erofs_pcpu_workers)
return -ENOMEM;
for_each_online_cpu(cpu) { /* could miss cpu{off,on}line? */
worker = erofs_init_percpu_worker(cpu);
if (!IS_ERR(worker))
rcu_assign_pointer(z_erofs_pcpu_workers[cpu], worker);
}
return 0;
}
#else
static inline void erofs_destroy_percpu_workers(void) {}
static inline int erofs_init_percpu_workers(void) { return 0; }
#endif
#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_EROFS_FS_PCPU_KTHREAD)
static DEFINE_SPINLOCK(z_erofs_pcpu_worker_lock);
static enum cpuhp_state erofs_cpuhp_state;
static int erofs_cpu_online(unsigned int cpu)
{
struct kthread_worker *worker, *old;
worker = erofs_init_percpu_worker(cpu);
if (IS_ERR(worker))
return PTR_ERR(worker);
spin_lock(&z_erofs_pcpu_worker_lock);
old = rcu_dereference_protected(z_erofs_pcpu_workers[cpu],
lockdep_is_held(&z_erofs_pcpu_worker_lock));
if (!old)
rcu_assign_pointer(z_erofs_pcpu_workers[cpu], worker);
spin_unlock(&z_erofs_pcpu_worker_lock);
if (old)
kthread_destroy_worker(worker);
return 0;
}
static int erofs_cpu_offline(unsigned int cpu)
{
struct kthread_worker *worker;
spin_lock(&z_erofs_pcpu_worker_lock);
worker = rcu_dereference_protected(z_erofs_pcpu_workers[cpu],
lockdep_is_held(&z_erofs_pcpu_worker_lock));
rcu_assign_pointer(z_erofs_pcpu_workers[cpu], NULL);
spin_unlock(&z_erofs_pcpu_worker_lock);
synchronize_rcu();
if (worker)
kthread_destroy_worker(worker);
return 0;
}
static int erofs_cpu_hotplug_init(void)
{
int state;
state = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
"fs/erofs:online", erofs_cpu_online, erofs_cpu_offline);
if (state < 0)
return state;
erofs_cpuhp_state = state;
return 0;
}
static void erofs_cpu_hotplug_destroy(void)
{
if (erofs_cpuhp_state)
cpuhp_remove_state_nocalls(erofs_cpuhp_state);
}
#else /* !CONFIG_HOTPLUG_CPU || !CONFIG_EROFS_FS_PCPU_KTHREAD */
static inline int erofs_cpu_hotplug_init(void) { return 0; }
static inline void erofs_cpu_hotplug_destroy(void) {}
#endif
void z_erofs_exit_zip_subsystem(void)
{
erofs_cpu_hotplug_destroy();
erofs_destroy_percpu_workers();
destroy_workqueue(z_erofs_workqueue);
z_erofs_destroy_pcluster_pool();
}
int __init z_erofs_init_zip_subsystem(void)
@@ -142,10 +246,31 @@ int __init z_erofs_init_zip_subsystem(void)
int err = z_erofs_create_pcluster_pool();
if (err)
return err;
err = z_erofs_init_workqueue();
goto out_error_pcluster_pool;
z_erofs_workqueue = alloc_workqueue("erofs_worker",
WQ_UNBOUND | WQ_HIGHPRI, num_possible_cpus());
if (!z_erofs_workqueue) {
err = -ENOMEM;
goto out_error_workqueue_init;
}
err = erofs_init_percpu_workers();
if (err)
z_erofs_destroy_pcluster_pool();
goto out_error_pcpu_worker;
err = erofs_cpu_hotplug_init();
if (err < 0)
goto out_error_cpuhp_init;
return err;
out_error_cpuhp_init:
erofs_destroy_percpu_workers();
out_error_pcpu_worker:
destroy_workqueue(z_erofs_workqueue);
out_error_workqueue_init:
z_erofs_destroy_pcluster_pool();
out_error_pcluster_pool:
return err;
}
@@ -763,6 +888,12 @@ static int z_erofs_do_read_page(struct z_erofs_decompress_frontend *fe,
}
static void z_erofs_decompressqueue_work(struct work_struct *work);
#ifdef CONFIG_EROFS_FS_PCPU_KTHREAD
static void z_erofs_decompressqueue_kthread_work(struct kthread_work *work)
{
z_erofs_decompressqueue_work((struct work_struct *)work);
}
#endif
static void z_erofs_decompress_kickoff(struct z_erofs_decompressqueue *io,
bool sync, int bios)
{
@@ -780,7 +911,22 @@ static void z_erofs_decompress_kickoff(struct z_erofs_decompressqueue *io,
return;
/* Use workqueue and sync decompression for atomic contexts only */
if (in_atomic() || irqs_disabled()) {
#ifdef CONFIG_EROFS_FS_PCPU_KTHREAD
struct kthread_worker *worker;
rcu_read_lock();
worker = rcu_dereference(
z_erofs_pcpu_workers[raw_smp_processor_id()]);
if (!worker) {
INIT_WORK(&io->u.work, z_erofs_decompressqueue_work);
queue_work(z_erofs_workqueue, &io->u.work);
} else {
kthread_queue_work(worker, &io->u.kthread_work);
}
rcu_read_unlock();
#else
queue_work(z_erofs_workqueue, &io->u.work);
#endif
sbi->opt.readahead_sync_decompress = true;
return;
}
@@ -1049,7 +1195,6 @@ static void z_erofs_decompressqueue_work(struct work_struct *work)
DBG_BUGON(bgq->head == Z_EROFS_PCLUSTER_TAIL_CLOSED);
z_erofs_decompress_queue(bgq, &pagepool);
erofs_release_pages(&pagepool);
kvfree(bgq);
}
@@ -1179,7 +1324,12 @@ jobqueue_init(struct super_block *sb,
*fg = true;
goto fg_out;
}
#ifdef CONFIG_EROFS_FS_PCPU_KTHREAD
kthread_init_work(&q->u.kthread_work,
z_erofs_decompressqueue_kthread_work);
#else
INIT_WORK(&q->u.work, z_erofs_decompressqueue_work);
#endif
} else {
fg_out:
q = fgq;
@@ -1330,7 +1480,7 @@ static void z_erofs_submit_queue(struct super_block *sb,
/*
* although background is preferred, no one is pending for submission.
* don't issue workqueue for decompression but drop it directly instead.
* don't issue decompression but drop it directly instead.
*/
if (!*force_fg && !nr_bios) {
kvfree(q[JQ_SUBMIT]);

View File

@@ -6,6 +6,7 @@
#ifndef __EROFS_FS_ZDATA_H
#define __EROFS_FS_ZDATA_H
#include <linux/kthread.h>
#include "internal.h"
#include "zpvec.h"
@@ -91,6 +92,7 @@ struct z_erofs_decompressqueue {
union {
struct completion done;
struct work_struct work;
struct kthread_work kthread_work;
} u;
};

View File

@@ -1016,7 +1016,6 @@ static int exec_mmap(struct mm_struct *mm)
active_mm = tsk->active_mm;
tsk->active_mm = mm;
tsk->mm = mm;
lru_gen_add_mm(mm);
/*
* This prevents preemption while active_mm is being loaded and
* it and mm are being updated, which could cause problems for
@@ -1030,6 +1029,7 @@ static int exec_mmap(struct mm_struct *mm)
if (IS_ENABLED(CONFIG_ARCH_WANT_IRQS_OFF_ACTIVATE_MM))
local_irq_enable();
tsk->mm->vmacache_seqnum = 0;
lru_gen_add_mm(mm);
vmacache_flush(tsk);
task_unlock(tsk);
lru_gen_use_mm(mm);

View File

@@ -292,15 +292,10 @@ void ext4_release_system_zone(struct super_block *sb)
call_rcu(&system_blks->rcu, ext4_destroy_system_zone);
}
/*
* Returns 1 if the passed-in block region (start_blk,
* start_blk+count) is valid; 0 if some part of the block region
* overlaps with some other filesystem metadata blocks.
*/
int ext4_inode_block_valid(struct inode *inode, ext4_fsblk_t start_blk,
unsigned int count)
int ext4_sb_block_valid(struct super_block *sb, struct inode *inode,
ext4_fsblk_t start_blk, unsigned int count)
{
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
struct ext4_sb_info *sbi = EXT4_SB(sb);
struct ext4_system_blocks *system_blks;
struct ext4_system_zone *entry;
struct rb_node *n;
@@ -329,7 +324,9 @@ int ext4_inode_block_valid(struct inode *inode, ext4_fsblk_t start_blk,
else if (start_blk >= (entry->start_blk + entry->count))
n = n->rb_right;
else {
ret = (entry->ino == inode->i_ino);
ret = 0;
if (inode)
ret = (entry->ino == inode->i_ino);
break;
}
}
@@ -338,6 +335,17 @@ int ext4_inode_block_valid(struct inode *inode, ext4_fsblk_t start_blk,
return ret;
}
/*
* Returns 1 if the passed-in block region (start_blk,
* start_blk+count) is valid; 0 if some part of the block region
* overlaps with some other filesystem metadata blocks.
*/
int ext4_inode_block_valid(struct inode *inode, ext4_fsblk_t start_blk,
unsigned int count)
{
return ext4_sb_block_valid(inode->i_sb, inode, start_blk, count);
}
int ext4_check_blockref(const char *function, unsigned int line,
struct inode *inode, __le32 *p, unsigned int max)
{

View File

@@ -3698,6 +3698,9 @@ extern int ext4_inode_block_valid(struct inode *inode,
unsigned int count);
extern int ext4_check_blockref(const char *, unsigned int,
struct inode *, __le32 *, unsigned int);
extern int ext4_sb_block_valid(struct super_block *sb, struct inode *inode,
ext4_fsblk_t start_blk, unsigned int count);
/* extents.c */
struct ext4_ext_path;

View File

@@ -486,6 +486,8 @@ static int ext4_getfsmap_datadev(struct super_block *sb,
keys[0].fmr_physical = bofs;
if (keys[1].fmr_physical >= eofs)
keys[1].fmr_physical = eofs - 1;
if (keys[1].fmr_physical < keys[0].fmr_physical)
return 0;
start_fsb = keys[0].fmr_physical;
end_fsb = keys[1].fmr_physical;

View File

@@ -5888,7 +5888,8 @@ static void ext4_free_blocks_simple(struct inode *inode, ext4_fsblk_t block,
}
/**
* ext4_free_blocks() -- Free given blocks and update quota
* ext4_mb_clear_bb() -- helper function for freeing blocks.
* Used by ext4_free_blocks()
* @handle: handle for this transaction
* @inode: inode
* @bh: optional buffer of the block to be freed
@@ -5896,9 +5897,9 @@ static void ext4_free_blocks_simple(struct inode *inode, ext4_fsblk_t block,
* @count: number of blocks to be freed
* @flags: flags used by ext4_free_blocks
*/
void ext4_free_blocks(handle_t *handle, struct inode *inode,
struct buffer_head *bh, ext4_fsblk_t block,
unsigned long count, int flags)
static void ext4_mb_clear_bb(handle_t *handle, struct inode *inode,
ext4_fsblk_t block, unsigned long count,
int flags)
{
struct buffer_head *bitmap_bh = NULL;
struct super_block *sb = inode->i_sb;
@@ -5915,79 +5916,14 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
sbi = EXT4_SB(sb);
if (sbi->s_mount_state & EXT4_FC_REPLAY) {
ext4_free_blocks_simple(inode, block, count);
return;
}
might_sleep();
if (bh) {
if (block)
BUG_ON(block != bh->b_blocknr);
else
block = bh->b_blocknr;
}
if (!(flags & EXT4_FREE_BLOCKS_VALIDATED) &&
!ext4_inode_block_valid(inode, block, count)) {
ext4_error(sb, "Freeing blocks not in datazone - "
"block = %llu, count = %lu", block, count);
ext4_error(sb, "Freeing blocks in system zone - "
"Block = %llu, count = %lu", block, count);
/* err = 0. ext4_std_error should be a no op */
goto error_return;
}
ext4_debug("freeing block %llu\n", block);
trace_ext4_free_blocks(inode, block, count, flags);
if (bh && (flags & EXT4_FREE_BLOCKS_FORGET)) {
BUG_ON(count > 1);
ext4_forget(handle, flags & EXT4_FREE_BLOCKS_METADATA,
inode, bh, block);
}
/*
* If the extent to be freed does not begin on a cluster
* boundary, we need to deal with partial clusters at the
* beginning and end of the extent. Normally we will free
* blocks at the beginning or the end unless we are explicitly
* requested to avoid doing so.
*/
overflow = EXT4_PBLK_COFF(sbi, block);
if (overflow) {
if (flags & EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER) {
overflow = sbi->s_cluster_ratio - overflow;
block += overflow;
if (count > overflow)
count -= overflow;
else
return;
} else {
block -= overflow;
count += overflow;
}
}
overflow = EXT4_LBLK_COFF(sbi, count);
if (overflow) {
if (flags & EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER) {
if (count > overflow)
count -= overflow;
else
return;
} else
count += sbi->s_cluster_ratio - overflow;
}
if (!bh && (flags & EXT4_FREE_BLOCKS_FORGET)) {
int i;
int is_metadata = flags & EXT4_FREE_BLOCKS_METADATA;
for (i = 0; i < count; i++) {
cond_resched();
if (is_metadata)
bh = sb_find_get_block(inode->i_sb, block + i);
ext4_forget(handle, is_metadata, inode, bh, block + i);
}
}
flags |= EXT4_FREE_BLOCKS_VALIDATED;
do_more:
overflow = 0;
@@ -6005,6 +5941,8 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
overflow = EXT4_C2B(sbi, bit) + count -
EXT4_BLOCKS_PER_GROUP(sb);
count -= overflow;
/* The range changed so it's no longer validated */
flags &= ~EXT4_FREE_BLOCKS_VALIDATED;
}
count_clusters = EXT4_NUM_B2C(sbi, count);
bitmap_bh = ext4_read_block_bitmap(sb, block_group);
@@ -6019,13 +5957,8 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
goto error_return;
}
if (in_range(ext4_block_bitmap(sb, gdp), block, count) ||
in_range(ext4_inode_bitmap(sb, gdp), block, count) ||
in_range(block, ext4_inode_table(sb, gdp),
sbi->s_itb_per_group) ||
in_range(block + count - 1, ext4_inode_table(sb, gdp),
sbi->s_itb_per_group)) {
if (!(flags & EXT4_FREE_BLOCKS_VALIDATED) &&
!ext4_inode_block_valid(inode, block, count)) {
ext4_error(sb, "Freeing blocks in system zone - "
"Block = %llu, count = %lu", block, count);
/* err = 0. ext4_std_error should be a no op */
@@ -6096,7 +6029,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
NULL);
if (err && err != -EOPNOTSUPP)
ext4_msg(sb, KERN_WARNING, "discard request in"
" group:%d block:%d count:%lu failed"
" group:%u block:%d count:%lu failed"
" with %d", block_group, bit, count,
err);
} else
@@ -6148,6 +6081,8 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
block += count;
count = overflow;
put_bh(bitmap_bh);
/* The range changed so it's no longer validated */
flags &= ~EXT4_FREE_BLOCKS_VALIDATED;
goto do_more;
}
error_return:
@@ -6156,6 +6091,108 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
return;
}
/**
* ext4_free_blocks() -- Free given blocks and update quota
* @handle: handle for this transaction
* @inode: inode
* @bh: optional buffer of the block to be freed
* @block: starting physical block to be freed
* @count: number of blocks to be freed
* @flags: flags used by ext4_free_blocks
*/
void ext4_free_blocks(handle_t *handle, struct inode *inode,
struct buffer_head *bh, ext4_fsblk_t block,
unsigned long count, int flags)
{
struct super_block *sb = inode->i_sb;
unsigned int overflow;
struct ext4_sb_info *sbi;
sbi = EXT4_SB(sb);
if (sbi->s_mount_state & EXT4_FC_REPLAY) {
ext4_free_blocks_simple(inode, block, count);
return;
}
might_sleep();
if (bh) {
if (block)
BUG_ON(block != bh->b_blocknr);
else
block = bh->b_blocknr;
}
if (!(flags & EXT4_FREE_BLOCKS_VALIDATED) &&
!ext4_inode_block_valid(inode, block, count)) {
ext4_error(sb, "Freeing blocks not in datazone - "
"block = %llu, count = %lu", block, count);
return;
}
flags |= EXT4_FREE_BLOCKS_VALIDATED;
ext4_debug("freeing block %llu\n", block);
trace_ext4_free_blocks(inode, block, count, flags);
if (bh && (flags & EXT4_FREE_BLOCKS_FORGET)) {
BUG_ON(count > 1);
ext4_forget(handle, flags & EXT4_FREE_BLOCKS_METADATA,
inode, bh, block);
}
/*
* If the extent to be freed does not begin on a cluster
* boundary, we need to deal with partial clusters at the
* beginning and end of the extent. Normally we will free
* blocks at the beginning or the end unless we are explicitly
* requested to avoid doing so.
*/
overflow = EXT4_PBLK_COFF(sbi, block);
if (overflow) {
if (flags & EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER) {
overflow = sbi->s_cluster_ratio - overflow;
block += overflow;
if (count > overflow)
count -= overflow;
else
return;
} else {
block -= overflow;
count += overflow;
}
/* The range changed so it's no longer validated */
flags &= ~EXT4_FREE_BLOCKS_VALIDATED;
}
overflow = EXT4_LBLK_COFF(sbi, count);
if (overflow) {
if (flags & EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER) {
if (count > overflow)
count -= overflow;
else
return;
} else
count += sbi->s_cluster_ratio - overflow;
/* The range changed so it's no longer validated */
flags &= ~EXT4_FREE_BLOCKS_VALIDATED;
}
if (!bh && (flags & EXT4_FREE_BLOCKS_FORGET)) {
int i;
int is_metadata = flags & EXT4_FREE_BLOCKS_METADATA;
for (i = 0; i < count; i++) {
cond_resched();
if (is_metadata)
bh = sb_find_get_block(inode->i_sb, block + i);
ext4_forget(handle, is_metadata, inode, bh, block + i);
}
}
ext4_mb_clear_bb(handle, inode, block, count, flags);
return;
}
/**
* ext4_group_add_blocks() -- Add given blocks to an existing group
* @handle: handle to this transaction
@@ -6212,11 +6249,7 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
goto error_return;
}
if (in_range(ext4_block_bitmap(sb, desc), block, count) ||
in_range(ext4_inode_bitmap(sb, desc), block, count) ||
in_range(block, ext4_inode_table(sb, desc), sbi->s_itb_per_group) ||
in_range(block + count - 1, ext4_inode_table(sb, desc),
sbi->s_itb_per_group)) {
if (!ext4_sb_block_valid(sb, NULL, block, count)) {
ext4_error(sb, "Adding blocks in system zones - "
"Block = %llu, count = %lu",
block, count);

View File

@@ -1422,6 +1422,13 @@ static struct inode *ext4_xattr_inode_create(handle_t *handle,
uid_t owner[2] = { i_uid_read(inode), i_gid_read(inode) };
int err;
if (inode->i_sb->s_root == NULL) {
ext4_warning(inode->i_sb,
"refuse to create EA inode when umounting");
WARN_ON(1);
return ERR_PTR(-EINVAL);
}
/*
* Let the next inode be the goal, so we try and allocate the EA inode
* in the same group, or nearby one.
@@ -2549,9 +2556,8 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
is = kzalloc(sizeof(struct ext4_xattr_ibody_find), GFP_NOFS);
bs = kzalloc(sizeof(struct ext4_xattr_block_find), GFP_NOFS);
buffer = kvmalloc(value_size, GFP_NOFS);
b_entry_name = kmalloc(entry->e_name_len + 1, GFP_NOFS);
if (!is || !bs || !buffer || !b_entry_name) {
if (!is || !bs || !b_entry_name) {
error = -ENOMEM;
goto out;
}
@@ -2563,12 +2569,18 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
/* Save the entry name and the entry value */
if (entry->e_value_inum) {
buffer = kvmalloc(value_size, GFP_NOFS);
if (!buffer) {
error = -ENOMEM;
goto out;
}
error = ext4_xattr_inode_get(inode, entry, buffer, value_size);
if (error)
goto out;
} else {
size_t value_offs = le16_to_cpu(entry->e_value_offs);
memcpy(buffer, (void *)IFIRST(header) + value_offs, value_size);
buffer = (void *)IFIRST(header) + value_offs;
}
memcpy(b_entry_name, entry->e_name, entry->e_name_len);
@@ -2583,25 +2595,26 @@ static int ext4_xattr_move_to_block(handle_t *handle, struct inode *inode,
if (error)
goto out;
/* Remove the chosen entry from the inode */
error = ext4_xattr_ibody_set(handle, inode, &i, is);
if (error)
goto out;
i.value = buffer;
i.value_len = value_size;
error = ext4_xattr_block_find(inode, &i, bs);
if (error)
goto out;
/* Add entry which was removed from the inode into the block */
/* Move ea entry from the inode into the block */
error = ext4_xattr_block_set(handle, inode, &i, bs);
if (error)
goto out;
error = 0;
/* Remove the chosen entry from the inode */
i.value = NULL;
i.value_len = 0;
error = ext4_xattr_ibody_set(handle, inode, &i, is);
out:
kfree(b_entry_name);
kvfree(buffer);
if (entry->e_value_inum && buffer)
kvfree(buffer);
if (is)
brelse(is->iloc.bh);
if (bs)

View File

@@ -92,16 +92,6 @@ static int gc_thread_func(void *data)
* invalidated soon after by user update or deletion.
* So, I'd like to wait some time to collect dirty segments.
*/
if (sbi->gc_mode == GC_URGENT_HIGH) {
spin_lock(&sbi->gc_urgent_high_lock);
if (sbi->gc_urgent_high_remaining) {
sbi->gc_urgent_high_remaining--;
if (!sbi->gc_urgent_high_remaining)
sbi->gc_mode = GC_NORMAL;
}
spin_unlock(&sbi->gc_urgent_high_lock);
}
if (sbi->gc_mode == GC_URGENT_HIGH ||
sbi->gc_mode == GC_URGENT_MID) {
wait_ms = gc_th->urgent_sleep_time;
@@ -151,6 +141,15 @@ static int gc_thread_func(void *data)
/* balancing f2fs's metadata periodically */
f2fs_balance_fs_bg(sbi, true);
next:
if (sbi->gc_mode == GC_URGENT_HIGH) {
spin_lock(&sbi->gc_urgent_high_lock);
if (sbi->gc_urgent_high_remaining) {
sbi->gc_urgent_high_remaining--;
if (!sbi->gc_urgent_high_remaining)
sbi->gc_mode = GC_NORMAL;
}
spin_unlock(&sbi->gc_urgent_high_lock);
}
sb_end_write(sbi->sb);
} while (!kthread_should_stop());

View File

@@ -52,3 +52,11 @@ config FUSE_DAX
If you want to allow mounting a Virtio Filesystem with the "dax"
option, answer Y.
config FUSE_BPF
bool "Adds BPF to fuse"
depends on FUSE_FS
depends on BPF
help
Extends FUSE by adding BPF to prefilter calls and potentially pass to a
backing file system

View File

@@ -10,5 +10,6 @@ obj-$(CONFIG_VIRTIO_FS) += virtiofs.o
fuse-y := dev.o dir.o file.o inode.o control.o xattr.o acl.o readdir.o ioctl.o
fuse-y += passthrough.o
fuse-$(CONFIG_FUSE_DAX) += dax.o
fuse-$(CONFIG_FUSE_BPF) += backing.o
virtiofs-y := virtio_fs.o

2473
fs/fuse/backing.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -395,7 +395,7 @@ int __init fuse_ctl_init(void)
return register_filesystem(&fuse_ctl_fs_type);
}
void __exit fuse_ctl_cleanup(void)
void fuse_ctl_cleanup(void)
{
unregister_filesystem(&fuse_ctl_fs_type);
}

View File

@@ -242,6 +242,11 @@ void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget,
{
struct fuse_iqueue *fiq = &fc->iq;
if (nodeid == 0) {
kfree(forget);
return;
}
forget->forget_one.nodeid = nodeid;
forget->forget_one.nlookup = nlookup;
@@ -483,6 +488,7 @@ static void fuse_args_to_req(struct fuse_req *req, struct fuse_args *args)
{
req->in.h.opcode = args->opcode;
req->in.h.nodeid = args->nodeid;
req->in.h.padding = args->error_in;
req->args = args;
if (args->end)
__set_bit(FR_ASYNC, &req->flags);
@@ -1943,6 +1949,19 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud,
kern_path(path, 0, req->args->canonical_path);
}
if (!err && (req->in.h.opcode == FUSE_LOOKUP ||
req->in.h.opcode == (FUSE_LOOKUP | FUSE_POSTFILTER)) &&
req->args->out_args[1].size == sizeof(struct fuse_entry_bpf_out)) {
struct fuse_entry_bpf_out *febo = (struct fuse_entry_bpf_out *)
req->args->out_args[1].value;
struct fuse_entry_bpf *feb = container_of(febo, struct fuse_entry_bpf, out);
if (febo->backing_action == FUSE_ACTION_REPLACE)
feb->backing_file = fget(febo->backing_fd);
if (febo->bpf_action == FUSE_ACTION_REPLACE)
feb->bpf_file = fget(febo->bpf_fd);
}
spin_lock(&fpq->lock);
clear_bit(FR_LOCKED, &req->flags);
if (!fpq->connected)

View File

@@ -8,8 +8,10 @@
#include "fuse_i.h"
#include <linux/fdtable.h>
#include <linux/pagemap.h>
#include <linux/file.h>
#include <linux/filter.h>
#include <linux/fs_context.h>
#include <linux/sched.h>
#include <linux/namei.h>
@@ -21,6 +23,8 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include "../internal.h"
static void fuse_advise_use_readdirplus(struct inode *dir)
{
struct fuse_inode *fi = get_fuse_inode(dir);
@@ -28,7 +32,7 @@ static void fuse_advise_use_readdirplus(struct inode *dir)
set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state);
}
#if BITS_PER_LONG >= 64
#if BITS_PER_LONG >= 64 && !defined(CONFIG_FUSE_BPF)
static inline void __fuse_dentry_settime(struct dentry *entry, u64 time)
{
entry->d_fsdata = (void *) time;
@@ -40,19 +44,15 @@ static inline u64 fuse_dentry_time(const struct dentry *entry)
}
#else
union fuse_dentry {
u64 time;
struct rcu_head rcu;
};
static inline void __fuse_dentry_settime(struct dentry *dentry, u64 time)
{
((union fuse_dentry *) dentry->d_fsdata)->time = time;
((struct fuse_dentry *) dentry->d_fsdata)->time = time;
}
static inline u64 fuse_dentry_time(const struct dentry *entry)
{
return ((union fuse_dentry *) entry->d_fsdata)->time;
return ((struct fuse_dentry *) entry->d_fsdata)->time;
}
#endif
@@ -77,26 +77,16 @@ static void fuse_dentry_settime(struct dentry *dentry, u64 time)
__fuse_dentry_settime(dentry, time);
}
/*
* FUSE caches dentries and attributes with separate timeout. The
* time in jiffies until the dentry/attributes are valid is stored in
* dentry->d_fsdata and fuse_inode->i_time respectively.
*/
/*
* Calculate the time in jiffies until a dentry/attributes are valid
*/
static u64 time_to_jiffies(u64 sec, u32 nsec)
void fuse_init_dentry_root(struct dentry *root, struct file *backing_dir)
{
if (sec || nsec) {
struct timespec64 ts = {
sec,
min_t(u32, nsec, NSEC_PER_SEC - 1)
};
#ifdef CONFIG_FUSE_BPF
struct fuse_dentry *fuse_dentry = root->d_fsdata;
return get_jiffies_64() + timespec64_to_jiffies(&ts);
} else
return 0;
if (backing_dir) {
fuse_dentry->backing_path = backing_dir->f_path;
path_get(&fuse_dentry->backing_path);
}
#endif
}
/*
@@ -109,11 +99,6 @@ void fuse_change_entry_timeout(struct dentry *entry, struct fuse_entry_out *o)
time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
}
static u64 attr_timeout(struct fuse_attr_out *o)
{
return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
}
u64 entry_attr_timeout(struct fuse_entry_out *o)
{
return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
@@ -174,7 +159,8 @@ static void fuse_invalidate_entry(struct dentry *entry)
static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args,
u64 nodeid, const struct qstr *name,
struct fuse_entry_out *outarg)
struct fuse_entry_out *outarg,
struct fuse_entry_bpf_out *bpf_outarg)
{
memset(outarg, 0, sizeof(struct fuse_entry_out));
args->opcode = FUSE_LOOKUP;
@@ -182,11 +168,52 @@ static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args,
args->in_numargs = 1;
args->in_args[0].size = name->len + 1;
args->in_args[0].value = name->name;
args->out_numargs = 1;
args->out_argvar = true;
args->out_numargs = 2;
args->out_args[0].size = sizeof(struct fuse_entry_out);
args->out_args[0].value = outarg;
args->out_args[1].size = sizeof(struct fuse_entry_bpf_out);
args->out_args[1].value = bpf_outarg;
}
#ifdef CONFIG_FUSE_BPF
static bool backing_data_changed(struct fuse_inode *fi, struct dentry *entry,
struct fuse_entry_bpf *bpf_arg)
{
struct path new_backing_path;
struct inode *new_backing_inode;
struct bpf_prog *bpf = NULL;
int err;
bool ret = true;
if (!entry)
return false;
get_fuse_backing_path(entry, &new_backing_path);
new_backing_inode = fi->backing_inode;
ihold(new_backing_inode);
err = fuse_handle_backing(bpf_arg, &new_backing_inode, &new_backing_path);
if (err)
goto put_inode;
err = fuse_handle_bpf_prog(bpf_arg, entry->d_parent->d_inode, &bpf);
if (err)
goto put_bpf;
ret = (bpf != fi->bpf || fi->backing_inode != new_backing_inode ||
!path_equal(&get_fuse_dentry(entry)->backing_path, &new_backing_path));
put_bpf:
if (bpf)
bpf_prog_put(bpf);
put_inode:
iput(new_backing_inode);
path_put(&new_backing_path);
return ret;
}
#endif
/*
* Check whether the dentry is still valid
*
@@ -207,9 +234,23 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
inode = d_inode_rcu(entry);
if (inode && fuse_is_bad(inode))
goto invalid;
else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) ||
#ifdef CONFIG_FUSE_BPF
/* TODO: Do we need bpf support for revalidate?
* If the lower filesystem says the entry is invalid, FUSE probably shouldn't
* try to fix that without going through the normal lookup path...
*/
if (get_fuse_dentry(entry)->backing_path.dentry) {
ret = fuse_revalidate_backing(entry, flags);
if (ret <= 0) {
goto out;
}
}
#endif
if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) ||
(flags & (LOOKUP_EXCL | LOOKUP_REVAL))) {
struct fuse_entry_out outarg;
struct fuse_entry_bpf bpf_arg;
FUSE_ARGS(args);
struct fuse_forget_link *forget;
u64 attr_version;
@@ -221,27 +262,44 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
ret = -ECHILD;
if (flags & LOOKUP_RCU)
goto out;
fm = get_fuse_mount(inode);
parent = dget_parent(entry);
#ifdef CONFIG_FUSE_BPF
/* TODO: Once we're handling timeouts for backing inodes, do a
* bpf based lookup_revalidate here.
*/
if (get_fuse_inode(parent->d_inode)->backing_inode) {
dput(parent);
ret = 1;
goto out;
}
#endif
forget = fuse_alloc_forget();
ret = -ENOMEM;
if (!forget)
if (!forget) {
dput(parent);
goto out;
}
attr_version = fuse_get_attr_version(fm->fc);
parent = dget_parent(entry);
fuse_lookup_init(fm->fc, &args, get_node_id(d_inode(parent)),
&entry->d_name, &outarg);
&entry->d_name, &outarg, &bpf_arg.out);
ret = fuse_simple_request(fm, &args);
dput(parent);
/* Zero nodeid is same as -ENOENT */
if (!ret && !outarg.nodeid)
ret = -ENOENT;
if (!ret) {
if (!ret || ret == sizeof(bpf_arg.out)) {
fi = get_fuse_inode(inode);
if (outarg.nodeid != get_node_id(inode) ||
#ifdef CONFIG_FUSE_BPF
(ret == sizeof(bpf_arg.out) &&
backing_data_changed(fi, entry, &bpf_arg)) ||
#endif
(bool) IS_AUTOMOUNT(inode) != (bool) (outarg.attr.flags & FUSE_ATTR_SUBMOUNT)) {
fuse_queue_forget(fm->fc, forget,
outarg.nodeid, 1);
@@ -283,17 +341,20 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
goto out;
}
#if BITS_PER_LONG < 64
#if BITS_PER_LONG < 64 || defined(CONFIG_FUSE_BPF)
static int fuse_dentry_init(struct dentry *dentry)
{
dentry->d_fsdata = kzalloc(sizeof(union fuse_dentry),
dentry->d_fsdata = kzalloc(sizeof(struct fuse_dentry),
GFP_KERNEL_ACCOUNT | __GFP_RECLAIMABLE);
return dentry->d_fsdata ? 0 : -ENOMEM;
}
static void fuse_dentry_release(struct dentry *dentry)
{
union fuse_dentry *fd = dentry->d_fsdata;
struct fuse_dentry *fd = dentry->d_fsdata;
if (fd && fd->backing_path.dentry)
path_put(&fd->backing_path);
kfree_rcu(fd, rcu);
}
@@ -347,6 +408,18 @@ static void fuse_dentry_canonical_path(const struct path *path,
char *path_name;
int err;
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(inode, struct fuse_dummy_io,
fuse_canonical_path_initialize,
fuse_canonical_path_backing,
fuse_canonical_path_finalize, path,
canonical_path);
if (fer.ret)
return;
#endif
path_name = (char *)get_zeroed_page(GFP_KERNEL);
if (!path_name)
goto default_path;
@@ -373,7 +446,7 @@ static void fuse_dentry_canonical_path(const struct path *path,
const struct dentry_operations fuse_dentry_operations = {
.d_revalidate = fuse_dentry_revalidate,
.d_delete = fuse_dentry_delete,
#if BITS_PER_LONG < 64
#if BITS_PER_LONG < 64 || defined(CONFIG_FUSE_BPF)
.d_init = fuse_dentry_init,
.d_release = fuse_dentry_release,
#endif
@@ -382,7 +455,7 @@ const struct dentry_operations fuse_dentry_operations = {
};
const struct dentry_operations fuse_root_dentry_operations = {
#if BITS_PER_LONG < 64
#if BITS_PER_LONG < 64 || defined(CONFIG_FUSE_BPF)
.d_init = fuse_dentry_init,
.d_release = fuse_dentry_release,
#endif
@@ -401,10 +474,13 @@ bool fuse_invalid_attr(struct fuse_attr *attr)
}
int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
struct fuse_entry_out *outarg, struct inode **inode)
struct fuse_entry_out *outarg,
struct dentry *entry,
struct inode **inode)
{
struct fuse_mount *fm = get_fuse_mount_super(sb);
FUSE_ARGS(args);
struct fuse_entry_bpf bpf_arg = {0};
struct fuse_forget_link *forget;
u64 attr_version;
int err;
@@ -422,23 +498,68 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name
attr_version = fuse_get_attr_version(fm->fc);
fuse_lookup_init(fm->fc, &args, nodeid, name, outarg);
fuse_lookup_init(fm->fc, &args, nodeid, name, outarg, &bpf_arg.out);
err = fuse_simple_request(fm, &args);
/* Zero nodeid is same as -ENOENT, but with valid timeout */
if (err || !outarg->nodeid)
goto out_put_forget;
err = -EIO;
if (!outarg->nodeid)
goto out_put_forget;
if (fuse_invalid_attr(&outarg->attr))
goto out_put_forget;
#ifdef CONFIG_FUSE_BPF
if (err == sizeof(bpf_arg.out)) {
/* TODO Make sure this handles invalid handles */
struct file *backing_file;
struct inode *backing_inode;
err = -ENOENT;
if (!entry)
goto out_queue_forget;
err = -EINVAL;
backing_file = bpf_arg.backing_file;
if (!backing_file)
goto out_queue_forget;
if (IS_ERR(backing_file)) {
err = PTR_ERR(backing_file);
goto out_queue_forget;
}
backing_inode = backing_file->f_inode;
*inode = fuse_iget_backing(sb, outarg->nodeid, backing_inode);
if (!*inode)
goto bpf_arg_out;
err = fuse_handle_backing(&bpf_arg,
&get_fuse_inode(*inode)->backing_inode,
&get_fuse_dentry(entry)->backing_path);
if (err)
goto out;
err = fuse_handle_bpf_prog(&bpf_arg, NULL, &get_fuse_inode(*inode)->bpf);
if (err)
goto out;
bpf_arg_out:
fput(backing_file);
} else
#endif
{
/* Zero nodeid is same as -ENOENT, but with valid timeout */
if (err || !outarg->nodeid)
goto out_put_forget;
err = -EIO;
if (!outarg->nodeid)
goto out_put_forget;
if (fuse_invalid_attr(&outarg->attr))
goto out_put_forget;
*inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
&outarg->attr, entry_attr_timeout(outarg),
attr_version);
}
*inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
&outarg->attr, entry_attr_timeout(outarg),
attr_version);
err = -ENOMEM;
if (!*inode) {
#ifdef CONFIG_FUSE_BPF
out_queue_forget:
#endif
if (!*inode && outarg->nodeid) {
fuse_queue_forget(fm->fc, forget, outarg->nodeid, 1);
goto out;
}
@@ -460,12 +581,23 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
bool outarg_valid = true;
bool locked;
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(dir, struct fuse_lookup_io,
fuse_lookup_initialize, fuse_lookup_backing,
fuse_lookup_finalize,
dir, entry, flags);
if (fer.ret)
return fer.result;
#endif
if (fuse_is_bad(dir))
return ERR_PTR(-EIO);
locked = fuse_lock_inode(dir);
err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
&outarg, &inode);
&outarg, entry, &inode);
fuse_unlock_inode(dir, locked);
if (err == -ENOENT) {
outarg_valid = false;
@@ -582,6 +714,20 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
/* Userspace expects S_IFREG in create mode */
BUG_ON((mode & S_IFMT) != S_IFREG);
#ifdef CONFIG_FUSE_BPF
{
struct fuse_err_ret fer;
fer = fuse_bpf_backing(dir, struct fuse_create_open_io,
fuse_create_open_initialize,
fuse_create_open_backing,
fuse_create_open_finalize,
dir, entry, file, flags, mode);
if (fer.ret)
return PTR_ERR(fer.result);
}
#endif
forget = fuse_alloc_forget();
err = -ENOMEM;
if (!forget)
@@ -811,6 +957,17 @@ static int fuse_mknod(struct user_namespace *mnt_userns, struct inode *dir,
struct fuse_mount *fm = get_fuse_mount(dir);
FUSE_ARGS(args);
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(dir, struct fuse_mknod_in,
fuse_mknod_initialize, fuse_mknod_backing,
fuse_mknod_finalize,
dir, entry, mode, rdev);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
if (!fm->fc->dont_mask)
mode &= ~current_umask();
@@ -840,6 +997,17 @@ static int fuse_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
struct fuse_mount *fm = get_fuse_mount(dir);
FUSE_ARGS(args);
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(dir, struct fuse_mkdir_in,
fuse_mkdir_initialize, fuse_mkdir_backing,
fuse_mkdir_finalize,
dir, entry, mode);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
if (!fm->fc->dont_mask)
mode &= ~current_umask();
@@ -862,6 +1030,17 @@ static int fuse_symlink(struct user_namespace *mnt_userns, struct inode *dir,
unsigned len = strlen(link) + 1;
FUSE_ARGS(args);
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(dir, struct fuse_dummy_io,
fuse_symlink_initialize, fuse_symlink_backing,
fuse_symlink_finalize,
dir, entry, link, len);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
args.opcode = FUSE_SYMLINK;
args.in_numargs = 2;
args.in_args[0].size = entry->d_name.len + 1;
@@ -896,6 +1075,20 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
if (fuse_is_bad(dir))
return -EIO;
#ifdef CONFIG_FUSE_BPF
{
struct fuse_err_ret fer;
fer = fuse_bpf_backing(dir, struct fuse_dummy_io,
fuse_unlink_initialize,
fuse_unlink_backing,
fuse_unlink_finalize,
dir, entry);
if (fer.ret)
return PTR_ERR(fer.result);
}
#endif
args.opcode = FUSE_UNLINK;
args.nodeid = get_node_id(dir);
args.in_numargs = 1;
@@ -935,6 +1128,20 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
if (fuse_is_bad(dir))
return -EIO;
#ifdef CONFIG_FUSE_BPF
{
struct fuse_err_ret fer;
fer = fuse_bpf_backing(dir, struct fuse_dummy_io,
fuse_rmdir_initialize,
fuse_rmdir_backing,
fuse_rmdir_finalize,
dir, entry);
if (fer.ret)
return PTR_ERR(fer.result);
}
#endif
args.opcode = FUSE_RMDIR;
args.nodeid = get_node_id(dir);
args.in_numargs = 1;
@@ -1020,6 +1227,18 @@ static int fuse_rename2(struct user_namespace *mnt_userns, struct inode *olddir,
return -EINVAL;
if (flags) {
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(olddir, struct fuse_rename2_in,
fuse_rename2_initialize, fuse_rename2_backing,
fuse_rename2_finalize,
olddir, oldent, newdir, newent, flags);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
/* TODO: how should this go with bpfs involved? */
if (fc->no_rename2 || fc->minor < 23)
return -EINVAL;
@@ -1031,6 +1250,17 @@ static int fuse_rename2(struct user_namespace *mnt_userns, struct inode *olddir,
err = -EINVAL;
}
} else {
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(olddir, struct fuse_rename_in,
fuse_rename_initialize, fuse_rename_backing,
fuse_rename_finalize,
olddir, oldent, newdir, newent);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
err = fuse_rename_common(olddir, oldent, newdir, newent, 0,
FUSE_RENAME,
sizeof(struct fuse_rename_in));
@@ -1048,6 +1278,16 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
struct fuse_mount *fm = get_fuse_mount(inode);
FUSE_ARGS(args);
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(inode, struct fuse_link_in, fuse_link_initialize,
fuse_link_backing, fuse_link_finalize, entry,
newdir, newent);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
memset(&inarg, 0, sizeof(inarg));
inarg.oldnodeid = get_node_id(inode);
args.opcode = FUSE_LINK;
@@ -1079,7 +1319,7 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
return err;
}
static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
struct kstat *stat)
{
unsigned int blkbits;
@@ -1148,23 +1388,13 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
args.out_args[0].size = sizeof(outarg);
args.out_args[0].value = &outarg;
err = fuse_simple_request(fm, &args);
if (!err) {
if (fuse_invalid_attr(&outarg.attr) ||
inode_wrong_type(inode, outarg.attr.mode)) {
fuse_make_bad(inode);
err = -EIO;
} else {
fuse_change_attributes(inode, &outarg.attr,
attr_timeout(&outarg),
attr_version);
if (stat)
fuse_fillattr(inode, &outarg.attr, stat);
}
}
if (!err)
err = finalize_attr(inode, &outarg, attr_version, stat);
return err;
}
static int fuse_update_get_attr(struct inode *inode, struct file *file,
const struct path *path,
struct kstat *stat, u32 request_mask,
unsigned int flags)
{
@@ -1172,6 +1402,17 @@ static int fuse_update_get_attr(struct inode *inode, struct file *file,
int err = 0;
bool sync;
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(inode, struct fuse_getattr_io,
fuse_getattr_initialize, fuse_getattr_backing,
fuse_getattr_finalize,
path->dentry, stat, request_mask, flags);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
if (flags & AT_STATX_FORCE_SYNC)
sync = true;
else if (flags & AT_STATX_DONT_SYNC)
@@ -1196,7 +1437,7 @@ static int fuse_update_get_attr(struct inode *inode, struct file *file,
int fuse_update_attributes(struct inode *inode, struct file *file)
{
/* Do *not* need to get atime for internal purposes */
return fuse_update_get_attr(inode, file, NULL,
return fuse_update_get_attr(inode, file, &file->f_path, NULL,
STATX_BASIC_STATS & ~STATX_ATIME, 0);
}
@@ -1305,6 +1546,16 @@ static int fuse_access(struct inode *inode, int mask)
struct fuse_access_in inarg;
int err;
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(inode, struct fuse_access_in,
fuse_access_initialize, fuse_access_backing,
fuse_access_finalize, inode, mask);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
BUG_ON(mask & MAY_NOT_BLOCK);
if (fm->fc->no_access)
@@ -1353,6 +1604,10 @@ static int fuse_permission(struct user_namespace *mnt_userns,
struct fuse_conn *fc = get_fuse_conn(inode);
bool refreshed = false;
int err = 0;
struct fuse_inode *fi = get_fuse_inode(inode);
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
#endif
if (fuse_is_bad(inode))
return -EIO;
@@ -1360,12 +1615,19 @@ static int fuse_permission(struct user_namespace *mnt_userns,
if (!fuse_allow_current_process(fc))
return -EACCES;
#ifdef CONFIG_FUSE_BPF
fer = fuse_bpf_backing(inode, struct fuse_access_in,
fuse_access_initialize, fuse_access_backing,
fuse_access_finalize, inode, mask);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
/*
* If attributes are needed, refresh them before proceeding
*/
if (fc->default_permissions ||
((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
struct fuse_inode *fi = get_fuse_inode(inode);
u32 perm_mask = STATX_MODE | STATX_UID | STATX_GID;
if (perm_mask & READ_ONCE(fi->inval_mask) ||
@@ -1456,6 +1718,21 @@ static const char *fuse_get_link(struct dentry *dentry, struct inode *inode,
if (fuse_is_bad(inode))
goto out_err;
#ifdef CONFIG_FUSE_BPF
{
struct fuse_err_ret fer;
const char *out = NULL;
fer = fuse_bpf_backing(inode, struct fuse_dummy_io,
fuse_get_link_initialize,
fuse_get_link_backing,
fuse_get_link_finalize,
inode, dentry, callback, &out);
if (fer.ret)
return fer.result ?: out;
}
#endif
if (fc->cache_symlinks)
return page_get_link(dentry, inode, callback);
@@ -1489,8 +1766,18 @@ static int fuse_dir_open(struct inode *inode, struct file *file)
static int fuse_dir_release(struct inode *inode, struct file *file)
{
fuse_release_common(file, true);
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(inode, struct fuse_release_in,
fuse_releasedir_initialize, fuse_release_backing,
fuse_release_finalize,
inode, file);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
fuse_release_common(file, true);
return 0;
}
@@ -1504,6 +1791,19 @@ static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
if (fuse_is_bad(inode))
return -EIO;
#ifdef CONFIG_FUSE_BPF
{
struct fuse_err_ret fer;
fer = fuse_bpf_backing(inode, struct fuse_fsync_in,
fuse_dir_fsync_initialize, fuse_fsync_backing,
fuse_fsync_finalize,
file, start, end, datasync);
if (fer.ret)
return PTR_ERR(fer.result);
}
#endif
if (fc->no_fsyncdir)
return 0;
@@ -1542,58 +1842,6 @@ static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
}
static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
{
/* Always update if mtime is explicitly set */
if (ivalid & ATTR_MTIME_SET)
return true;
/* Or if kernel i_mtime is the official one */
if (trust_local_mtime)
return true;
/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
return false;
/* In all other cases update */
return true;
}
static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr,
struct fuse_setattr_in *arg, bool trust_local_cmtime)
{
unsigned ivalid = iattr->ia_valid;
if (ivalid & ATTR_MODE)
arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
if (ivalid & ATTR_UID)
arg->valid |= FATTR_UID, arg->uid = from_kuid(fc->user_ns, iattr->ia_uid);
if (ivalid & ATTR_GID)
arg->valid |= FATTR_GID, arg->gid = from_kgid(fc->user_ns, iattr->ia_gid);
if (ivalid & ATTR_SIZE)
arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
if (ivalid & ATTR_ATIME) {
arg->valid |= FATTR_ATIME;
arg->atime = iattr->ia_atime.tv_sec;
arg->atimensec = iattr->ia_atime.tv_nsec;
if (!(ivalid & ATTR_ATIME_SET))
arg->valid |= FATTR_ATIME_NOW;
}
if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
arg->valid |= FATTR_MTIME;
arg->mtime = iattr->ia_mtime.tv_sec;
arg->mtimensec = iattr->ia_mtime.tv_nsec;
if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
arg->valid |= FATTR_MTIME_NOW;
}
if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
arg->valid |= FATTR_CTIME;
arg->ctime = iattr->ia_ctime.tv_sec;
arg->ctimensec = iattr->ia_ctime.tv_nsec;
}
}
/*
* Prevent concurrent writepages on inode
*
@@ -1708,6 +1956,16 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode);
bool fault_blocked = false;
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(inode, struct fuse_setattr_io,
fuse_setattr_initialize, fuse_setattr_backing,
fuse_setattr_finalize, dentry, attr, file);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
if (!fc->default_permissions)
attr->ia_valid |= ATTR_FORCE;
@@ -1882,11 +2140,22 @@ static int fuse_setattr(struct user_namespace *mnt_userns, struct dentry *entry,
* This should be done on write(), truncate() and chown().
*/
if (!fc->handle_killpriv && !fc->handle_killpriv_v2) {
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
/*
* ia_mode calculation may have used stale i_mode.
* Refresh and recalculate.
*/
ret = fuse_do_getattr(inode, NULL, file);
fer = fuse_bpf_backing(inode, struct fuse_getattr_io,
fuse_getattr_initialize, fuse_getattr_backing,
fuse_getattr_finalize,
entry, NULL, 0, 0);
if (fer.ret)
ret = PTR_ERR(fer.result);
else
#endif
ret = fuse_do_getattr(inode, NULL, file);
if (ret)
return ret;
@@ -1943,7 +2212,8 @@ static int fuse_getattr(struct user_namespace *mnt_userns,
return -EACCES;
}
return fuse_update_get_attr(inode, NULL, stat, request_mask, flags);
return fuse_update_get_attr(inode, NULL, path, stat, request_mask,
flags);
}
static const struct inode_operations fuse_dir_inode_operations = {

View File

@@ -8,6 +8,7 @@
#include "fuse_i.h"
#include <linux/filter.h>
#include <linux/pagemap.h>
#include <linux/slab.h>
#include <linux/kernel.h>
@@ -240,6 +241,20 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
if (err)
return err;
#ifdef CONFIG_FUSE_BPF
{
struct fuse_err_ret fer;
fer = fuse_bpf_backing(inode, struct fuse_open_io,
fuse_open_initialize,
fuse_open_backing,
fuse_open_finalize,
inode, file, isdir);
if (fer.ret)
return PTR_ERR(fer.result);
}
#endif
if (is_wb_truncate || dax_truncate) {
inode_lock(inode);
fuse_set_nowrite(inode);
@@ -343,6 +358,17 @@ static int fuse_release(struct inode *inode, struct file *file)
{
struct fuse_conn *fc = get_fuse_conn(inode);
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(inode, struct fuse_release_in,
fuse_release_initialize, fuse_release_backing,
fuse_release_finalize,
inode, file);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
/* see fuse_vma_close() for !writeback_cache case */
if (fc->writeback_cache)
write_inode_now(inode, 1);
@@ -482,6 +508,17 @@ static int fuse_flush(struct file *file, fl_owner_t id)
FUSE_ARGS(args);
int err;
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(file->f_inode, struct fuse_flush_in,
fuse_flush_initialize, fuse_flush_backing,
fuse_flush_finalize,
file, id);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
if (fuse_is_bad(inode))
return -EIO;
@@ -554,6 +591,17 @@ static int fuse_fsync(struct file *file, loff_t start, loff_t end,
struct fuse_conn *fc = get_fuse_conn(inode);
int err;
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(inode, struct fuse_fsync_in,
fuse_fsync_initialize, fuse_fsync_backing,
fuse_fsync_finalize,
file, start, end, datasync);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
if (fuse_is_bad(inode))
return -EIO;
@@ -1586,6 +1634,20 @@ static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
if (FUSE_IS_DAX(inode))
return fuse_dax_read_iter(iocb, to);
#ifdef CONFIG_FUSE_BPF
{
struct fuse_err_ret fer;
fer = fuse_bpf_backing(inode, struct fuse_file_read_iter_io,
fuse_file_read_iter_initialize,
fuse_file_read_iter_backing,
fuse_file_read_iter_finalize,
iocb, to);
if (fer.ret)
return PTR_ERR(fer.result);
}
#endif
if (ff->passthrough.filp)
return fuse_passthrough_read_iter(iocb, to);
else if (!(ff->open_flags & FOPEN_DIRECT_IO))
@@ -1606,6 +1668,20 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
if (FUSE_IS_DAX(inode))
return fuse_dax_write_iter(iocb, from);
#ifdef CONFIG_FUSE_BPF
{
struct fuse_err_ret fer;
fer = fuse_bpf_backing(inode, struct fuse_file_write_iter_io,
fuse_file_write_iter_initialize,
fuse_file_write_iter_backing,
fuse_file_write_iter_finalize,
iocb, from);
if (fer.ret)
return PTR_ERR(fer.result);
}
#endif
if (ff->passthrough.filp)
return fuse_passthrough_write_iter(iocb, from);
else if (!(ff->open_flags & FOPEN_DIRECT_IO))
@@ -1855,6 +1931,19 @@ int fuse_write_inode(struct inode *inode, struct writeback_control *wbc)
struct fuse_file *ff;
int err;
/**
* TODO - fully understand why this is necessary
*
* With fuse-bpf, fsstress fails if rename is enabled without this
*
* We are getting writes here on directory inodes, which do not have an
* initialized file list so crash.
*
* The question is why we are getting those writes
*/
if (!S_ISREG(inode->i_mode))
return 0;
/*
* Inode is always written before the last reference is dropped and
* hence this should not be reached from reclaim.
@@ -2413,6 +2502,12 @@ static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
if (FUSE_IS_DAX(file_inode(file)))
return fuse_dax_mmap(file, vma);
#ifdef CONFIG_FUSE_BPF
/* TODO - this is simply passthrough, not a proper BPF filter */
if (ff->backing_file)
return fuse_backing_mmap(file, vma);
#endif
if (ff->passthrough.filp)
return fuse_passthrough_mmap(file, vma);
@@ -2661,6 +2756,17 @@ static loff_t fuse_file_llseek(struct file *file, loff_t offset, int whence)
{
loff_t retval;
struct inode *inode = file_inode(file);
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(inode, struct fuse_lseek_io,
fuse_lseek_initialize,
fuse_lseek_backing,
fuse_lseek_finalize,
file, offset, whence);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
switch (whence) {
case SEEK_SET:
@@ -2951,6 +3057,18 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
(!(mode & FALLOC_FL_KEEP_SIZE) ||
(mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE)));
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(inode, struct fuse_fallocate_in,
fuse_file_fallocate_initialize,
fuse_file_fallocate_backing,
fuse_file_fallocate_finalize,
file, mode, offset, length);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
FALLOC_FL_ZERO_RANGE))
return -EOPNOTSUPP;
@@ -3056,6 +3174,18 @@ static ssize_t __fuse_copy_file_range(struct file *file_in, loff_t pos_in,
bool is_unstable = (!fc->writeback_cache) &&
((pos_out + len) > inode_out->i_size);
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(file_in->f_inode, struct fuse_copy_file_range_io,
fuse_copy_file_range_initialize,
fuse_copy_file_range_backing,
fuse_copy_file_range_finalize,
file_in, pos_in, file_out, pos_out, len, flags);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
if (fc->no_copy_file_range)
return -EOPNOTSUPP;

View File

@@ -13,6 +13,9 @@
# define pr_fmt(fmt) "fuse: " fmt
#endif
#include <linux/android_fuse.h>
#include <linux/filter.h>
#include <linux/pagemap.h>
#include <linux/fuse.h>
#include <linux/fs.h>
#include <linux/mount.h>
@@ -31,6 +34,9 @@
#include <linux/pid_namespace.h>
#include <linux/refcount.h>
#include <linux/user_namespace.h>
#include <linux/statfs.h>
#define FUSE_SUPER_MAGIC 0x65735546
/** Default max number of pages that can be used in a single read request */
#define FUSE_DEFAULT_MAX_PAGES_PER_REQ 32
@@ -63,11 +69,57 @@ struct fuse_forget_link {
struct fuse_forget_link *next;
};
/** FUSE specific dentry data */
#if BITS_PER_LONG < 64 || defined(CONFIG_FUSE_BPF)
struct fuse_dentry {
union {
u64 time;
struct rcu_head rcu;
};
struct path backing_path;
};
static inline struct fuse_dentry *get_fuse_dentry(const struct dentry *entry)
{
return entry->d_fsdata;
}
#endif
#ifdef CONFIG_FUSE_BPF
static inline void get_fuse_backing_path(const struct dentry *d,
struct path *path)
{
struct fuse_dentry *di = get_fuse_dentry(d);
if (!di) {
*path = (struct path) {};
return;
}
*path = di->backing_path;
path_get(path);
}
#endif
/** FUSE inode */
struct fuse_inode {
/** Inode data */
struct inode inode;
#ifdef CONFIG_FUSE_BPF
/**
* Backing inode, if this inode is from a backing file system.
* If this is set, nodeid is 0.
*/
struct inode *backing_inode;
/**
* bpf_prog, run on all operations to determine whether to pass through
* or handle in place
*/
struct bpf_prog *bpf;
#endif
/** Unique ID, which identifies the inode between userspace
* and kernel */
u64 nodeid;
@@ -232,6 +284,14 @@ struct fuse_file {
/** Container for data related to the passthrough functionality */
struct fuse_passthrough passthrough;
#ifdef CONFIG_FUSE_BPF
/**
* TODO: Reconcile with passthrough file
* backing file when in bpf mode
*/
struct file *backing_file;
#endif
/** RB node to be linked on fuse_conn->polled_files */
struct rb_node polled_node;
@@ -263,6 +323,7 @@ struct fuse_page_desc {
struct fuse_args {
uint64_t nodeid;
uint32_t opcode;
uint32_t error_in;
unsigned short in_numargs;
unsigned short out_numargs;
bool force:1;
@@ -275,8 +336,8 @@ struct fuse_args {
bool page_zeroing:1;
bool page_replace:1;
bool may_block:1;
struct fuse_in_arg in_args[3];
struct fuse_arg out_args[2];
struct fuse_in_arg in_args[FUSE_MAX_IN_ARGS];
struct fuse_arg out_args[FUSE_MAX_OUT_ARGS];
void (*end)(struct fuse_mount *fm, struct fuse_args *args, int error);
/* Path used for completing d_canonical_path */
@@ -514,9 +575,12 @@ struct fuse_fs_context {
bool no_force_umount:1;
bool legacy_opts_show:1;
bool dax:1;
bool no_daemon:1;
unsigned int max_read;
unsigned int blksize;
const char *subtype;
struct bpf_prog *root_bpf;
struct file *root_dir;
/* DAX device, may be NULL */
struct dax_device *dax_dev;
@@ -787,6 +851,9 @@ struct fuse_conn {
/* Initialize security xattrs when creating a new inode */
unsigned int init_security:1;
/** BPF Only, no Daemon running */
unsigned int no_daemon:1;
/** The number of requests waiting for completion */
atomic_t num_waiting;
@@ -958,14 +1025,18 @@ extern const struct dentry_operations fuse_dentry_operations;
extern const struct dentry_operations fuse_root_dentry_operations;
/**
* Get a filled in inode
* Get a filled-in inode
*/
struct inode *fuse_iget_backing(struct super_block *sb,
u64 nodeid,
struct inode *backing_inode);
struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
int generation, struct fuse_attr *attr,
u64 attr_valid, u64 attr_version);
int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
struct fuse_entry_out *outarg, struct inode **inode);
struct fuse_entry_out *outarg,
struct dentry *entry, struct inode **inode);
/**
* Send FORGET command
@@ -1002,7 +1073,6 @@ struct fuse_io_args {
void fuse_read_args_fill(struct fuse_io_args *ia, struct file *file, loff_t pos,
size_t count, int opcode);
/**
* Send OPEN or OPENDIR request
*/
@@ -1072,7 +1142,7 @@ int fuse_dev_init(void);
void fuse_dev_cleanup(void);
int fuse_ctl_init(void);
void __exit fuse_ctl_cleanup(void);
void fuse_ctl_cleanup(void);
/**
* Simple request sending that does request allocation and freeing
@@ -1100,6 +1170,7 @@ void fuse_invalidate_entry_cache(struct dentry *entry);
void fuse_invalidate_atime(struct inode *inode);
u64 entry_attr_timeout(struct fuse_entry_out *o);
void fuse_init_dentry_root(struct dentry *root, struct file *backing_dir);
void fuse_change_entry_timeout(struct dentry *entry, struct fuse_entry_out *o);
/**
@@ -1311,6 +1382,7 @@ void fuse_file_release(struct inode *inode, struct fuse_file *ff,
unsigned int open_flags, fl_owner_t id, bool isdir);
/* passthrough.c */
void fuse_copyattr(struct file *dst_file, struct file *src_file);
int fuse_passthrough_open(struct fuse_dev *fud, u32 lower_fd);
int fuse_passthrough_setup(struct fuse_conn *fc, struct fuse_file *ff,
struct fuse_open_out *openarg);
@@ -1319,4 +1391,637 @@ ssize_t fuse_passthrough_read_iter(struct kiocb *iocb, struct iov_iter *to);
ssize_t fuse_passthrough_write_iter(struct kiocb *iocb, struct iov_iter *from);
ssize_t fuse_passthrough_mmap(struct file *file, struct vm_area_struct *vma);
/* backing.c */
/*
* Dummy io passed to fuse_bpf_backing when io operation needs no scratch space
*/
struct fuse_dummy_io {
int unused;
};
struct fuse_open_io {
struct fuse_open_in foi;
struct fuse_open_out foo;
};
int fuse_open_initialize(struct fuse_bpf_args *fa, struct fuse_open_io *foi,
struct inode *inode, struct file *file, bool isdir);
int fuse_open_backing(struct fuse_bpf_args *fa,
struct inode *inode, struct file *file, bool isdir);
void *fuse_open_finalize(struct fuse_bpf_args *fa,
struct inode *inode, struct file *file, bool isdir);
struct fuse_create_open_io {
struct fuse_create_in fci;
struct fuse_entry_out feo;
struct fuse_open_out foo;
};
int fuse_create_open_initialize(
struct fuse_bpf_args *fa, struct fuse_create_open_io *fcoi,
struct inode *dir, struct dentry *entry,
struct file *file, unsigned int flags, umode_t mode);
int fuse_create_open_backing(
struct fuse_bpf_args *fa,
struct inode *dir, struct dentry *entry,
struct file *file, unsigned int flags, umode_t mode);
void *fuse_create_open_finalize(
struct fuse_bpf_args *fa,
struct inode *dir, struct dentry *entry,
struct file *file, unsigned int flags, umode_t mode);
int fuse_mknod_initialize(
struct fuse_bpf_args *fa, struct fuse_mknod_in *fmi,
struct inode *dir, struct dentry *entry, umode_t mode, dev_t rdev);
int fuse_mknod_backing(
struct fuse_bpf_args *fa,
struct inode *dir, struct dentry *entry, umode_t mode, dev_t rdev);
void *fuse_mknod_finalize(
struct fuse_bpf_args *fa,
struct inode *dir, struct dentry *entry, umode_t mode, dev_t rdev);
int fuse_mkdir_initialize(
struct fuse_bpf_args *fa, struct fuse_mkdir_in *fmi,
struct inode *dir, struct dentry *entry, umode_t mode);
int fuse_mkdir_backing(
struct fuse_bpf_args *fa,
struct inode *dir, struct dentry *entry, umode_t mode);
void *fuse_mkdir_finalize(
struct fuse_bpf_args *fa,
struct inode *dir, struct dentry *entry, umode_t mode);
int fuse_rmdir_initialize(
struct fuse_bpf_args *fa, struct fuse_dummy_io *fmi,
struct inode *dir, struct dentry *entry);
int fuse_rmdir_backing(
struct fuse_bpf_args *fa,
struct inode *dir, struct dentry *entry);
void *fuse_rmdir_finalize(
struct fuse_bpf_args *fa,
struct inode *dir, struct dentry *entry);
int fuse_rename2_initialize(struct fuse_bpf_args *fa, struct fuse_rename2_in *fri,
struct inode *olddir, struct dentry *oldent,
struct inode *newdir, struct dentry *newent,
unsigned int flags);
int fuse_rename2_backing(struct fuse_bpf_args *fa,
struct inode *olddir, struct dentry *oldent,
struct inode *newdir, struct dentry *newent,
unsigned int flags);
void *fuse_rename2_finalize(struct fuse_bpf_args *fa,
struct inode *olddir, struct dentry *oldent,
struct inode *newdir, struct dentry *newent,
unsigned int flags);
int fuse_rename_initialize(struct fuse_bpf_args *fa, struct fuse_rename_in *fri,
struct inode *olddir, struct dentry *oldent,
struct inode *newdir, struct dentry *newent);
int fuse_rename_backing(struct fuse_bpf_args *fa,
struct inode *olddir, struct dentry *oldent,
struct inode *newdir, struct dentry *newent);
void *fuse_rename_finalize(struct fuse_bpf_args *fa,
struct inode *olddir, struct dentry *oldent,
struct inode *newdir, struct dentry *newent);
int fuse_unlink_initialize(
struct fuse_bpf_args *fa, struct fuse_dummy_io *fmi,
struct inode *dir, struct dentry *entry);
int fuse_unlink_backing(
struct fuse_bpf_args *fa,
struct inode *dir, struct dentry *entry);
void *fuse_unlink_finalize(
struct fuse_bpf_args *fa,
struct inode *dir, struct dentry *entry);
int fuse_link_initialize(struct fuse_bpf_args *fa, struct fuse_link_in *fli,
struct dentry *entry, struct inode *dir,
struct dentry *newent);
int fuse_link_backing(struct fuse_bpf_args *fa, struct dentry *entry,
struct inode *dir, struct dentry *newent);
void *fuse_link_finalize(struct fuse_bpf_args *fa, struct dentry *entry,
struct inode *dir, struct dentry *newent);
int fuse_release_initialize(struct fuse_bpf_args *fa, struct fuse_release_in *fri,
struct inode *inode, struct file *file);
int fuse_releasedir_initialize(struct fuse_bpf_args *fa,
struct fuse_release_in *fri,
struct inode *inode, struct file *file);
int fuse_release_backing(struct fuse_bpf_args *fa,
struct inode *inode, struct file *file);
void *fuse_release_finalize(struct fuse_bpf_args *fa,
struct inode *inode, struct file *file);
int fuse_flush_initialize(struct fuse_bpf_args *fa, struct fuse_flush_in *ffi,
struct file *file, fl_owner_t id);
int fuse_flush_backing(struct fuse_bpf_args *fa, struct file *file, fl_owner_t id);
void *fuse_flush_finalize(struct fuse_bpf_args *fa,
struct file *file, fl_owner_t id);
struct fuse_lseek_io {
struct fuse_lseek_in fli;
struct fuse_lseek_out flo;
};
int fuse_lseek_initialize(struct fuse_bpf_args *fa, struct fuse_lseek_io *fli,
struct file *file, loff_t offset, int whence);
int fuse_lseek_backing(struct fuse_bpf_args *fa, struct file *file, loff_t offset, int whence);
void *fuse_lseek_finalize(struct fuse_bpf_args *fa, struct file *file, loff_t offset, int whence);
struct fuse_copy_file_range_io {
struct fuse_copy_file_range_in fci;
struct fuse_write_out fwo;
};
int fuse_copy_file_range_initialize(struct fuse_bpf_args *fa,
struct fuse_copy_file_range_io *fcf,
struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out,
size_t len, unsigned int flags);
int fuse_copy_file_range_backing(struct fuse_bpf_args *fa,
struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out,
size_t len, unsigned int flags);
void *fuse_copy_file_range_finalize(struct fuse_bpf_args *fa,
struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out,
size_t len, unsigned int flags);
int fuse_fsync_initialize(struct fuse_bpf_args *fa, struct fuse_fsync_in *ffi,
struct file *file, loff_t start, loff_t end, int datasync);
int fuse_fsync_backing(struct fuse_bpf_args *fa,
struct file *file, loff_t start, loff_t end, int datasync);
void *fuse_fsync_finalize(struct fuse_bpf_args *fa,
struct file *file, loff_t start, loff_t end, int datasync);
int fuse_dir_fsync_initialize(struct fuse_bpf_args *fa, struct fuse_fsync_in *ffi,
struct file *file, loff_t start, loff_t end, int datasync);
struct fuse_getxattr_io {
struct fuse_getxattr_in fgi;
struct fuse_getxattr_out fgo;
};
int fuse_getxattr_initialize(
struct fuse_bpf_args *fa, struct fuse_getxattr_io *fgio,
struct dentry *dentry, const char *name, void *value,
size_t size);
int fuse_getxattr_backing(
struct fuse_bpf_args *fa,
struct dentry *dentry, const char *name, void *value,
size_t size);
void *fuse_getxattr_finalize(
struct fuse_bpf_args *fa,
struct dentry *dentry, const char *name, void *value,
size_t size);
int fuse_listxattr_initialize(struct fuse_bpf_args *fa,
struct fuse_getxattr_io *fgio,
struct dentry *dentry, char *list, size_t size);
int fuse_listxattr_backing(struct fuse_bpf_args *fa, struct dentry *dentry,
char *list, size_t size);
void *fuse_listxattr_finalize(struct fuse_bpf_args *fa, struct dentry *dentry,
char *list, size_t size);
int fuse_setxattr_initialize(struct fuse_bpf_args *fa,
struct fuse_setxattr_in *fsxi,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags);
int fuse_setxattr_backing(struct fuse_bpf_args *fa, struct dentry *dentry,
const char *name, const void *value, size_t size,
int flags);
void *fuse_setxattr_finalize(struct fuse_bpf_args *fa, struct dentry *dentry,
const char *name, const void *value, size_t size,
int flags);
int fuse_removexattr_initialize(struct fuse_bpf_args *fa,
struct fuse_dummy_io *unused,
struct dentry *dentry, const char *name);
int fuse_removexattr_backing(struct fuse_bpf_args *fa,
struct dentry *dentry, const char *name);
void *fuse_removexattr_finalize(struct fuse_bpf_args *fa,
struct dentry *dentry, const char *name);
struct fuse_read_iter_out {
uint64_t ret;
};
struct fuse_file_read_iter_io {
struct fuse_read_in fri;
struct fuse_read_iter_out frio;
};
int fuse_file_read_iter_initialize(
struct fuse_bpf_args *fa, struct fuse_file_read_iter_io *fri,
struct kiocb *iocb, struct iov_iter *to);
int fuse_file_read_iter_backing(struct fuse_bpf_args *fa,
struct kiocb *iocb, struct iov_iter *to);
void *fuse_file_read_iter_finalize(struct fuse_bpf_args *fa,
struct kiocb *iocb, struct iov_iter *to);
struct fuse_write_iter_out {
uint64_t ret;
};
struct fuse_file_write_iter_io {
struct fuse_write_in fwi;
struct fuse_write_out fwo;
struct fuse_write_iter_out fwio;
};
int fuse_file_write_iter_initialize(
struct fuse_bpf_args *fa, struct fuse_file_write_iter_io *fwio,
struct kiocb *iocb, struct iov_iter *from);
int fuse_file_write_iter_backing(struct fuse_bpf_args *fa,
struct kiocb *iocb, struct iov_iter *from);
void *fuse_file_write_iter_finalize(struct fuse_bpf_args *fa,
struct kiocb *iocb, struct iov_iter *from);
ssize_t fuse_backing_mmap(struct file *file, struct vm_area_struct *vma);
int fuse_file_fallocate_initialize(struct fuse_bpf_args *fa,
struct fuse_fallocate_in *ffi,
struct file *file, int mode, loff_t offset, loff_t length);
int fuse_file_fallocate_backing(struct fuse_bpf_args *fa,
struct file *file, int mode, loff_t offset, loff_t length);
void *fuse_file_fallocate_finalize(struct fuse_bpf_args *fa,
struct file *file, int mode, loff_t offset, loff_t length);
struct fuse_lookup_io {
struct fuse_entry_out feo;
struct fuse_entry_bpf feb;
};
int fuse_handle_backing(struct fuse_entry_bpf *feb, struct inode **backing_inode,
struct path *backing_path);
int fuse_handle_bpf_prog(struct fuse_entry_bpf *feb, struct inode *parent,
struct bpf_prog **bpf);
int fuse_lookup_initialize(struct fuse_bpf_args *fa, struct fuse_lookup_io *feo,
struct inode *dir, struct dentry *entry, unsigned int flags);
int fuse_lookup_backing(struct fuse_bpf_args *fa, struct inode *dir,
struct dentry *entry, unsigned int flags);
struct dentry *fuse_lookup_finalize(struct fuse_bpf_args *fa, struct inode *dir,
struct dentry *entry, unsigned int flags);
int fuse_revalidate_backing(struct dentry *entry, unsigned int flags);
int fuse_canonical_path_initialize(struct fuse_bpf_args *fa,
struct fuse_dummy_io *fdi,
const struct path *path,
struct path *canonical_path);
int fuse_canonical_path_backing(struct fuse_bpf_args *fa, const struct path *path,
struct path *canonical_path);
void *fuse_canonical_path_finalize(struct fuse_bpf_args *fa,
const struct path *path,
struct path *canonical_path);
struct fuse_getattr_io {
struct fuse_getattr_in fgi;
struct fuse_attr_out fao;
};
int fuse_getattr_initialize(struct fuse_bpf_args *fa, struct fuse_getattr_io *fgio,
const struct dentry *entry, struct kstat *stat,
u32 request_mask, unsigned int flags);
int fuse_getattr_backing(struct fuse_bpf_args *fa,
const struct dentry *entry, struct kstat *stat,
u32 request_mask, unsigned int flags);
void *fuse_getattr_finalize(struct fuse_bpf_args *fa,
const struct dentry *entry, struct kstat *stat,
u32 request_mask, unsigned int flags);
struct fuse_setattr_io {
struct fuse_setattr_in fsi;
struct fuse_attr_out fao;
};
int fuse_setattr_initialize(struct fuse_bpf_args *fa, struct fuse_setattr_io *fsi,
struct dentry *dentry, struct iattr *attr, struct file *file);
int fuse_setattr_backing(struct fuse_bpf_args *fa,
struct dentry *dentry, struct iattr *attr, struct file *file);
void *fuse_setattr_finalize(struct fuse_bpf_args *fa,
struct dentry *dentry, struct iattr *attr, struct file *file);
int fuse_statfs_initialize(struct fuse_bpf_args *fa, struct fuse_statfs_out *fso,
struct dentry *dentry, struct kstatfs *buf);
int fuse_statfs_backing(struct fuse_bpf_args *fa,
struct dentry *dentry, struct kstatfs *buf);
void *fuse_statfs_finalize(struct fuse_bpf_args *fa,
struct dentry *dentry, struct kstatfs *buf);
int fuse_get_link_initialize(struct fuse_bpf_args *fa, struct fuse_dummy_io *dummy,
struct inode *inode, struct dentry *dentry,
struct delayed_call *callback, const char **out);
int fuse_get_link_backing(struct fuse_bpf_args *fa,
struct inode *inode, struct dentry *dentry,
struct delayed_call *callback, const char **out);
void *fuse_get_link_finalize(struct fuse_bpf_args *fa,
struct inode *inode, struct dentry *dentry,
struct delayed_call *callback, const char **out);
int fuse_symlink_initialize(
struct fuse_bpf_args *fa, struct fuse_dummy_io *unused,
struct inode *dir, struct dentry *entry, const char *link, int len);
int fuse_symlink_backing(
struct fuse_bpf_args *fa,
struct inode *dir, struct dentry *entry, const char *link, int len);
void *fuse_symlink_finalize(
struct fuse_bpf_args *fa,
struct inode *dir, struct dentry *entry, const char *link, int len);
struct fuse_read_io {
struct fuse_read_in fri;
struct fuse_read_out fro;
};
int fuse_readdir_initialize(struct fuse_bpf_args *fa, struct fuse_read_io *frio,
struct file *file, struct dir_context *ctx,
bool *force_again, bool *allow_force, bool is_continued);
int fuse_readdir_backing(struct fuse_bpf_args *fa,
struct file *file, struct dir_context *ctx,
bool *force_again, bool *allow_force, bool is_continued);
void *fuse_readdir_finalize(struct fuse_bpf_args *fa,
struct file *file, struct dir_context *ctx,
bool *force_again, bool *allow_force, bool is_continued);
int fuse_access_initialize(struct fuse_bpf_args *fa, struct fuse_access_in *fai,
struct inode *inode, int mask);
int fuse_access_backing(struct fuse_bpf_args *fa, struct inode *inode, int mask);
void *fuse_access_finalize(struct fuse_bpf_args *fa, struct inode *inode, int mask);
/*
* FUSE caches dentries and attributes with separate timeout. The
* time in jiffies until the dentry/attributes are valid is stored in
* dentry->d_fsdata and fuse_inode->i_time respectively.
*/
/*
* Calculate the time in jiffies until a dentry/attributes are valid
*/
static inline u64 time_to_jiffies(u64 sec, u32 nsec)
{
if (sec || nsec) {
struct timespec64 ts = {
sec,
min_t(u32, nsec, NSEC_PER_SEC - 1)
};
return get_jiffies_64() + timespec64_to_jiffies(&ts);
} else
return 0;
}
static inline u64 attr_timeout(struct fuse_attr_out *o)
{
return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
}
static inline bool update_mtime(unsigned int ivalid, bool trust_local_mtime)
{
/* Always update if mtime is explicitly set */
if (ivalid & ATTR_MTIME_SET)
return true;
/* Or if kernel i_mtime is the official one */
if (trust_local_mtime)
return true;
/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
return false;
/* In all other cases update */
return true;
}
void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
struct kstat *stat);
static inline void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr,
struct fuse_setattr_in *arg, bool trust_local_cmtime)
{
unsigned int ivalid = iattr->ia_valid;
if (ivalid & ATTR_MODE)
arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
if (ivalid & ATTR_UID)
arg->valid |= FATTR_UID, arg->uid = from_kuid(fc->user_ns, iattr->ia_uid);
if (ivalid & ATTR_GID)
arg->valid |= FATTR_GID, arg->gid = from_kgid(fc->user_ns, iattr->ia_gid);
if (ivalid & ATTR_SIZE)
arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
if (ivalid & ATTR_ATIME) {
arg->valid |= FATTR_ATIME;
arg->atime = iattr->ia_atime.tv_sec;
arg->atimensec = iattr->ia_atime.tv_nsec;
if (!(ivalid & ATTR_ATIME_SET))
arg->valid |= FATTR_ATIME_NOW;
}
if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
arg->valid |= FATTR_MTIME;
arg->mtime = iattr->ia_mtime.tv_sec;
arg->mtimensec = iattr->ia_mtime.tv_nsec;
if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
arg->valid |= FATTR_MTIME_NOW;
}
if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
arg->valid |= FATTR_CTIME;
arg->ctime = iattr->ia_ctime.tv_sec;
arg->ctimensec = iattr->ia_ctime.tv_nsec;
}
}
static inline int finalize_attr(struct inode *inode, struct fuse_attr_out *outarg,
u64 attr_version, struct kstat *stat)
{
int err = 0;
if (fuse_invalid_attr(&outarg->attr) ||
((inode->i_mode ^ outarg->attr.mode) & S_IFMT)) {
fuse_make_bad(inode);
err = -EIO;
} else {
fuse_change_attributes(inode, &outarg->attr,
attr_timeout(outarg),
attr_version);
if (stat)
fuse_fillattr(inode, &outarg->attr, stat);
}
return err;
}
static inline void convert_statfs_to_fuse(struct fuse_kstatfs *attr, struct kstatfs *stbuf)
{
attr->bsize = stbuf->f_bsize;
attr->frsize = stbuf->f_frsize;
attr->blocks = stbuf->f_blocks;
attr->bfree = stbuf->f_bfree;
attr->bavail = stbuf->f_bavail;
attr->files = stbuf->f_files;
attr->ffree = stbuf->f_ffree;
attr->namelen = stbuf->f_namelen;
/* fsid is left zero */
}
static inline void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr)
{
stbuf->f_type = FUSE_SUPER_MAGIC;
stbuf->f_bsize = attr->bsize;
stbuf->f_frsize = attr->frsize;
stbuf->f_blocks = attr->blocks;
stbuf->f_bfree = attr->bfree;
stbuf->f_bavail = attr->bavail;
stbuf->f_files = attr->files;
stbuf->f_ffree = attr->ffree;
stbuf->f_namelen = attr->namelen;
/* fsid is left zero */
}
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret {
void *result;
bool ret;
};
int __init fuse_bpf_init(void);
void __exit fuse_bpf_cleanup(void);
ssize_t fuse_bpf_simple_request(struct fuse_mount *fm, struct fuse_bpf_args *args);
/*
* expression statement to wrap the backing filter logic
* struct inode *inode: inode with bpf and backing inode
* typedef io: (typically complex) type whose components fuse_args can point to.
* An instance of this type is created locally and passed to initialize
* void initialize(struct fuse_bpf_args *fa, io *in_out, args...): function that sets
* up fa and io based on args
* int backing(struct fuse_bpf_args *fa, args...): function that actually performs
* the backing io operation
* void *finalize(struct fuse_bpf_args *, args...): function that performs any final
* work needed to commit the backing io
*/
#define fuse_bpf_backing(inode, io, initialize, backing, finalize, \
args...) \
({ \
struct fuse_err_ret fer = {0}; \
int ext_flags; \
struct fuse_inode *fuse_inode = get_fuse_inode(inode); \
struct fuse_mount *fm = get_fuse_mount(inode); \
io feo = {0}; \
struct fuse_bpf_args fa = {0}, fa_backup = {0}; \
bool locked; \
ssize_t res; \
void *err; \
int i; \
bool initialized = false; \
\
do { \
if (!fuse_inode || !fuse_inode->backing_inode) \
break; \
\
err = ERR_PTR(initialize(&fa, &feo, args)); \
if (err) { \
fer = (struct fuse_err_ret) { \
err, \
true, \
}; \
break; \
} \
initialized = true; \
\
fa_backup = fa; \
fa.opcode |= FUSE_PREFILTER; \
for (i = 0; i < fa.in_numargs; ++i) \
fa.out_args[i] = (struct fuse_bpf_arg) { \
.size = fa.in_args[i].size, \
.value = (void *)fa.in_args[i].value, \
}; \
fa.out_numargs = fa.in_numargs; \
\
ext_flags = fuse_inode->bpf ? \
bpf_prog_run(fuse_inode->bpf, &fa) : \
FUSE_BPF_BACKING; \
if (ext_flags < 0) { \
fer = (struct fuse_err_ret) { \
ERR_PTR(ext_flags), \
true, \
}; \
break; \
} \
\
if (ext_flags & FUSE_BPF_USER_FILTER) { \
locked = fuse_lock_inode(inode); \
res = fuse_bpf_simple_request(fm, &fa); \
fuse_unlock_inode(inode, locked); \
if (res < 0) { \
fer = (struct fuse_err_ret) { \
ERR_PTR(res), \
true, \
}; \
break; \
} \
} \
\
if (!(ext_flags & FUSE_BPF_BACKING)) \
break; \
\
fa.opcode &= ~FUSE_PREFILTER; \
for (i = 0; i < fa.in_numargs; ++i) \
fa.in_args[i] = (struct fuse_bpf_in_arg) { \
.size = fa.out_args[i].size, \
.value = fa.out_args[i].value, \
}; \
for (i = 0; i < fa_backup.out_numargs; ++i) \
fa.out_args[i] = (struct fuse_bpf_arg) { \
.size = fa_backup.out_args[i].size, \
.value = fa_backup.out_args[i].value, \
}; \
fa.out_numargs = fa_backup.out_numargs; \
\
fer = (struct fuse_err_ret) { \
ERR_PTR(backing(&fa, args)), \
true, \
}; \
if (IS_ERR(fer.result)) \
fa.error_in = PTR_ERR(fer.result); \
if (!(ext_flags & FUSE_BPF_POST_FILTER)) \
break; \
\
fa.opcode |= FUSE_POSTFILTER; \
for (i = 0; i < fa.out_numargs; ++i) \
fa.in_args[fa.in_numargs++] = \
(struct fuse_bpf_in_arg) { \
.size = fa.out_args[i].size, \
.value = fa.out_args[i].value, \
}; \
ext_flags = bpf_prog_run(fuse_inode->bpf, &fa); \
if (ext_flags < 0) { \
fer = (struct fuse_err_ret) { \
ERR_PTR(ext_flags), \
true, \
}; \
break; \
} \
if (!(ext_flags & FUSE_BPF_USER_FILTER)) \
break; \
\
fa.out_args[0].size = fa_backup.out_args[0].size; \
fa.out_args[1].size = fa_backup.out_args[1].size; \
fa.out_numargs = fa_backup.out_numargs; \
locked = fuse_lock_inode(inode); \
res = fuse_bpf_simple_request(fm, &fa); \
fuse_unlock_inode(inode, locked); \
if (res < 0) { \
fer.result = ERR_PTR(res); \
break; \
} \
} while (false); \
\
if (initialized && fer.ret) { \
err = finalize(&fa, args); \
if (err) \
fer.result = err; \
} \
\
fer; \
})
#endif /* CONFIG_FUSE_BPF */
#endif /* _FS_FUSE_I_H */

View File

@@ -51,8 +51,6 @@ MODULE_PARM_DESC(max_user_congthresh,
"Global limit for the maximum congestion threshold an "
"unprivileged user can set");
#define FUSE_SUPER_MAGIC 0x65735546
#define FUSE_DEFAULT_BLKSIZE 512
/** Maximum number of outstanding background requests */
@@ -80,6 +78,10 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
fi->i_time = 0;
fi->inval_mask = 0;
#ifdef CONFIG_FUSE_BPF
fi->backing_inode = NULL;
fi->bpf = NULL;
#endif
fi->nodeid = 0;
fi->nlookup = 0;
fi->attr_version = 0;
@@ -122,6 +124,12 @@ static void fuse_evict_inode(struct inode *inode)
/* Will write inode on close/munmap and in all other dirtiers */
WARN_ON(inode->i_state & I_DIRTY_INODE);
#ifdef CONFIG_FUSE_BPF
iput(fi->backing_inode);
if (fi->bpf)
bpf_prog_put(fi->bpf);
fi->bpf = NULL;
#endif
truncate_inode_pages_final(&inode->i_data);
clear_inode(inode);
if (inode->i_sb->s_flags & SB_ACTIVE) {
@@ -164,6 +172,28 @@ static ino_t fuse_squash_ino(u64 ino64)
return ino;
}
static void fuse_fill_attr_from_inode(struct fuse_attr *attr,
const struct inode *inode)
{
*attr = (struct fuse_attr){
.ino = inode->i_ino,
.size = inode->i_size,
.blocks = inode->i_blocks,
.atime = inode->i_atime.tv_sec,
.mtime = inode->i_mtime.tv_sec,
.ctime = inode->i_ctime.tv_sec,
.atimensec = inode->i_atime.tv_nsec,
.mtimensec = inode->i_mtime.tv_nsec,
.ctimensec = inode->i_ctime.tv_nsec,
.mode = inode->i_mode,
.nlink = inode->i_nlink,
.uid = inode->i_uid.val,
.gid = inode->i_gid.val,
.rdev = inode->i_rdev,
.blksize = 1u << inode->i_blkbits,
};
}
void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
u64 attr_valid)
{
@@ -298,28 +328,104 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
fuse_init_common(inode);
init_special_inode(inode, inode->i_mode,
new_decode_dev(attr->rdev));
init_special_inode(inode, inode->i_mode, attr->rdev);
} else
BUG();
}
struct fuse_inode_identifier {
u64 nodeid;
struct inode *backing_inode;
};
static int fuse_inode_eq(struct inode *inode, void *_nodeidp)
{
u64 nodeid = *(u64 *) _nodeidp;
if (get_node_id(inode) == nodeid)
return 1;
else
return 0;
struct fuse_inode_identifier *fii =
(struct fuse_inode_identifier *) _nodeidp;
struct fuse_inode *fi = get_fuse_inode(inode);
return fii->nodeid == fi->nodeid;
}
static int fuse_inode_backing_eq(struct inode *inode, void *_nodeidp)
{
struct fuse_inode_identifier *fii =
(struct fuse_inode_identifier *) _nodeidp;
struct fuse_inode *fi = get_fuse_inode(inode);
return fii->nodeid == fi->nodeid
#ifdef CONFIG_FUSE_BPF
&& fii->backing_inode == fi->backing_inode
#endif
;
}
static int fuse_inode_set(struct inode *inode, void *_nodeidp)
{
u64 nodeid = *(u64 *) _nodeidp;
get_fuse_inode(inode)->nodeid = nodeid;
struct fuse_inode_identifier *fii =
(struct fuse_inode_identifier *) _nodeidp;
struct fuse_inode *fi = get_fuse_inode(inode);
fi->nodeid = fii->nodeid;
return 0;
}
static int fuse_inode_backing_set(struct inode *inode, void *_nodeidp)
{
struct fuse_inode_identifier *fii =
(struct fuse_inode_identifier *) _nodeidp;
struct fuse_inode *fi = get_fuse_inode(inode);
fi->nodeid = fii->nodeid;
#ifdef CONFIG_FUSE_BPF
fi->backing_inode = fii->backing_inode;
if (fi->backing_inode)
ihold(fi->backing_inode);
#endif
return 0;
}
struct inode *fuse_iget_backing(struct super_block *sb, u64 nodeid,
struct inode *backing_inode)
{
struct inode *inode;
struct fuse_inode *fi;
struct fuse_conn *fc = get_fuse_conn_super(sb);
struct fuse_inode_identifier fii = {
.nodeid = nodeid,
.backing_inode = backing_inode,
};
struct fuse_attr attr;
unsigned long hash = (unsigned long) backing_inode;
if (nodeid)
hash = nodeid;
fuse_fill_attr_from_inode(&attr, backing_inode);
inode = iget5_locked(sb, hash, fuse_inode_backing_eq,
fuse_inode_backing_set, &fii);
if (!inode)
return NULL;
if ((inode->i_state & I_NEW)) {
inode->i_flags |= S_NOATIME;
if (!fc->writeback_cache)
inode->i_flags |= S_NOCMTIME;
fuse_init_common(inode);
unlock_new_inode(inode);
}
fi = get_fuse_inode(inode);
fuse_init_inode(inode, &attr);
spin_lock(&fi->lock);
fi->nlookup++;
spin_unlock(&fi->lock);
return inode;
}
struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
int generation, struct fuse_attr *attr,
u64 attr_valid, u64 attr_version)
@@ -327,6 +433,9 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
struct inode *inode;
struct fuse_inode *fi;
struct fuse_conn *fc = get_fuse_conn_super(sb);
struct fuse_inode_identifier fii = {
.nodeid = nodeid,
};
/*
* Auto mount points get their node id from the submount root, which is
@@ -348,7 +457,7 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
}
retry:
inode = iget5_locked(sb, nodeid, fuse_inode_eq, fuse_inode_set, &nodeid);
inode = iget5_locked(sb, nodeid, fuse_inode_eq, fuse_inode_set, &fii);
if (!inode)
return NULL;
@@ -380,13 +489,16 @@ struct inode *fuse_ilookup(struct fuse_conn *fc, u64 nodeid,
{
struct fuse_mount *fm_iter;
struct inode *inode;
struct fuse_inode_identifier fii = {
.nodeid = nodeid,
};
WARN_ON(!rwsem_is_locked(&fc->killsb));
list_for_each_entry(fm_iter, &fc->mounts, fc_entry) {
if (!fm_iter->sb)
continue;
inode = ilookup5(fm_iter->sb, nodeid, fuse_inode_eq, &nodeid);
inode = ilookup5(fm_iter->sb, nodeid, fuse_inode_eq, &fii);
if (inode) {
if (fm)
*fm = fm_iter;
@@ -467,20 +579,6 @@ static void fuse_send_destroy(struct fuse_mount *fm)
}
}
static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr)
{
stbuf->f_type = FUSE_SUPER_MAGIC;
stbuf->f_bsize = attr->bsize;
stbuf->f_frsize = attr->frsize;
stbuf->f_blocks = attr->blocks;
stbuf->f_bfree = attr->bfree;
stbuf->f_bavail = attr->bavail;
stbuf->f_files = attr->files;
stbuf->f_ffree = attr->ffree;
stbuf->f_namelen = attr->namelen;
/* fsid is left zero */
}
static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf)
{
struct super_block *sb = dentry->d_sb;
@@ -488,12 +586,24 @@ static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf)
FUSE_ARGS(args);
struct fuse_statfs_out outarg;
int err;
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
#endif
if (!fuse_allow_current_process(fm->fc)) {
buf->f_type = FUSE_SUPER_MAGIC;
return 0;
}
#ifdef CONFIG_FUSE_BPF
fer = fuse_bpf_backing(dentry->d_inode, struct fuse_statfs_out,
fuse_statfs_initialize, fuse_statfs_backing,
fuse_statfs_finalize,
dentry, buf);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
memset(&outarg, 0, sizeof(outarg));
args.in_numargs = 0;
args.opcode = FUSE_STATFS;
@@ -610,6 +720,9 @@ enum {
OPT_ALLOW_OTHER,
OPT_MAX_READ,
OPT_BLKSIZE,
OPT_ROOT_BPF,
OPT_ROOT_DIR,
OPT_NO_DAEMON,
OPT_ERR
};
@@ -624,6 +737,9 @@ static const struct fs_parameter_spec fuse_fs_parameters[] = {
fsparam_u32 ("max_read", OPT_MAX_READ),
fsparam_u32 ("blksize", OPT_BLKSIZE),
fsparam_string ("subtype", OPT_SUBTYPE),
fsparam_u32 ("root_bpf", OPT_ROOT_BPF),
fsparam_u32 ("root_dir", OPT_ROOT_DIR),
fsparam_flag ("no_daemon", OPT_NO_DAEMON),
{}
};
@@ -707,6 +823,26 @@ static int fuse_parse_param(struct fs_context *fsc, struct fs_parameter *param)
ctx->blksize = result.uint_32;
break;
case OPT_ROOT_BPF:
ctx->root_bpf = bpf_prog_get_type_dev(result.uint_32,
BPF_PROG_TYPE_FUSE, false);
if (IS_ERR(ctx->root_bpf)) {
ctx->root_bpf = NULL;
return invalfc(fsc, "Unable to open bpf program");
}
break;
case OPT_ROOT_DIR:
ctx->root_dir = fget(result.uint_32);
if (!ctx->root_dir)
return invalfc(fsc, "Unable to open root directory");
break;
case OPT_NO_DAEMON:
ctx->no_daemon = true;
ctx->fd_present = true;
break;
default:
return -EINVAL;
}
@@ -719,6 +855,10 @@ static void fuse_free_fsc(struct fs_context *fsc)
struct fuse_fs_context *ctx = fsc->fs_private;
if (ctx) {
if (ctx->root_dir)
fput(ctx->root_dir);
if (ctx->root_bpf)
bpf_prog_put(ctx->root_bpf);
kfree(ctx->subtype);
kfree(ctx);
}
@@ -844,15 +984,34 @@ struct fuse_conn *fuse_conn_get(struct fuse_conn *fc)
}
EXPORT_SYMBOL_GPL(fuse_conn_get);
static struct inode *fuse_get_root_inode(struct super_block *sb, unsigned mode)
static struct inode *fuse_get_root_inode(struct super_block *sb,
unsigned int mode,
struct bpf_prog *root_bpf,
struct file *backing_fd)
{
struct fuse_attr attr;
memset(&attr, 0, sizeof(attr));
struct inode *inode;
memset(&attr, 0, sizeof(attr));
attr.mode = mode;
attr.ino = FUSE_ROOT_ID;
attr.nlink = 1;
return fuse_iget(sb, 1, 0, &attr, 0, 0);
inode = fuse_iget(sb, 1, 0, &attr, 0, 0);
if (!inode)
return NULL;
#ifdef CONFIG_FUSE_BPF
get_fuse_inode(inode)->bpf = root_bpf;
if (root_bpf)
bpf_prog_inc(root_bpf);
if (backing_fd) {
get_fuse_inode(inode)->backing_inode = backing_fd->f_inode;
ihold(backing_fd->f_inode);
}
#endif
return inode;
}
struct fuse_inode_handle {
@@ -867,11 +1026,14 @@ static struct dentry *fuse_get_dentry(struct super_block *sb,
struct inode *inode;
struct dentry *entry;
int err = -ESTALE;
struct fuse_inode_identifier fii = {
.nodeid = handle->nodeid,
};
if (handle->nodeid == 0)
goto out_err;
inode = ilookup5(sb, handle->nodeid, fuse_inode_eq, &handle->nodeid);
inode = ilookup5(sb, handle->nodeid, fuse_inode_eq, &fii);
if (!inode) {
struct fuse_entry_out outarg;
const struct qstr name = QSTR_INIT(".", 1);
@@ -880,7 +1042,7 @@ static struct dentry *fuse_get_dentry(struct super_block *sb,
goto out_err;
err = fuse_lookup_name(sb, handle->nodeid, &name, &outarg,
&inode);
NULL, &inode);
if (err && err != -ENOENT)
goto out_err;
if (err || !inode) {
@@ -974,13 +1136,14 @@ static struct dentry *fuse_get_parent(struct dentry *child)
struct inode *inode;
struct dentry *parent;
struct fuse_entry_out outarg;
const struct qstr name = QSTR_INIT("..", 2);
int err;
if (!fc->export_support)
return ERR_PTR(-ESTALE);
err = fuse_lookup_name(child_inode->i_sb, get_node_id(child_inode),
&dotdot_name, &outarg, &inode);
&name, &outarg, NULL, &inode);
if (err) {
if (err == -ENOENT)
return ERR_PTR(-ESTALE);
@@ -1237,7 +1400,7 @@ void fuse_send_init(struct fuse_mount *fm)
ia->args.nocreds = true;
ia->args.end = process_init_reply;
if (fuse_simple_background(fm, &ia->args, GFP_KERNEL) != 0)
if (unlikely(fm->fc->no_daemon) || fuse_simple_background(fm, &ia->args, GFP_KERNEL) != 0)
process_init_reply(fm, &ia->args, -ENOTCONN);
}
EXPORT_SYMBOL_GPL(fuse_send_init);
@@ -1361,28 +1524,6 @@ void fuse_dev_free(struct fuse_dev *fud)
}
EXPORT_SYMBOL_GPL(fuse_dev_free);
static void fuse_fill_attr_from_inode(struct fuse_attr *attr,
const struct fuse_inode *fi)
{
*attr = (struct fuse_attr){
.ino = fi->inode.i_ino,
.size = fi->inode.i_size,
.blocks = fi->inode.i_blocks,
.atime = fi->inode.i_atime.tv_sec,
.mtime = fi->inode.i_mtime.tv_sec,
.ctime = fi->inode.i_ctime.tv_sec,
.atimensec = fi->inode.i_atime.tv_nsec,
.mtimensec = fi->inode.i_mtime.tv_nsec,
.ctimensec = fi->inode.i_ctime.tv_nsec,
.mode = fi->inode.i_mode,
.nlink = fi->inode.i_nlink,
.uid = fi->inode.i_uid.val,
.gid = fi->inode.i_gid.val,
.rdev = fi->inode.i_rdev,
.blksize = 1u << fi->inode.i_blkbits,
};
}
static void fuse_sb_defaults(struct super_block *sb)
{
sb->s_magic = FUSE_SUPER_MAGIC;
@@ -1426,7 +1567,7 @@ static int fuse_fill_super_submount(struct super_block *sb,
if (parent_sb->s_subtype && !sb->s_subtype)
return -ENOMEM;
fuse_fill_attr_from_inode(&root_attr, parent_fi);
fuse_fill_attr_from_inode(&root_attr, &parent_fi->inode);
root = fuse_iget(sb, parent_fi->nodeid, 0, &root_attr, 0, 0);
/*
* This inode is just a duplicate, so it is not looked up and
@@ -1553,13 +1694,16 @@ int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
fc->destroy = ctx->destroy;
fc->no_control = ctx->no_control;
fc->no_force_umount = ctx->no_force_umount;
fc->no_daemon = ctx->no_daemon;
err = -ENOMEM;
root = fuse_get_root_inode(sb, ctx->rootmode);
root = fuse_get_root_inode(sb, ctx->rootmode, ctx->root_bpf,
ctx->root_dir);
sb->s_d_op = &fuse_root_dentry_operations;
root_dentry = d_make_root(root);
if (!root_dentry)
goto err_dev_free;
fuse_init_dentry_root(root_dentry, ctx->root_dir);
/* Root dentry doesn't have .d_revalidate */
sb->s_d_op = &fuse_dentry_operations;
@@ -1598,18 +1742,20 @@ static int fuse_fill_super(struct super_block *sb, struct fs_context *fsc)
struct fuse_fs_context *ctx = fsc->fs_private;
int err;
if (!ctx->file || !ctx->rootmode_present ||
!ctx->user_id_present || !ctx->group_id_present)
return -EINVAL;
if (!ctx->no_daemon) {
if (!ctx->file || !ctx->rootmode_present ||
!ctx->user_id_present || !ctx->group_id_present)
return -EINVAL;
/*
* Require mount to happen from the same user namespace which
* opened /dev/fuse to prevent potential attacks.
*/
if ((ctx->file->f_op != &fuse_dev_operations) ||
(ctx->file->f_cred->user_ns != sb->s_user_ns))
return -EINVAL;
ctx->fudptr = &ctx->file->private_data;
/*
* Require mount to happen from the same user namespace which
* opened /dev/fuse to prevent potential attacks.
*/
if ((ctx->file->f_op != &fuse_dev_operations) ||
(ctx->file->f_cred->user_ns != sb->s_user_ns))
return -EINVAL;
ctx->fudptr = &ctx->file->private_data;
}
err = fuse_fill_super_common(sb, ctx);
if (err)
@@ -1890,6 +2036,57 @@ static void fuse_fs_cleanup(void)
static struct kobject *fuse_kobj;
static ssize_t fuse_bpf_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buff)
{
return sysfs_emit(buff, "supported\n");
}
static struct kobj_attribute fuse_bpf_attr =
__ATTR_RO(fuse_bpf);
static struct attribute *bpf_features[] = {
&fuse_bpf_attr.attr,
NULL,
};
static const struct attribute_group bpf_features_group = {
.name = "features",
.attrs = bpf_features,
};
/*
* TODO Remove this once fuse-bpf is upstreamed
*
* bpf_prog_type_fuse exports the bpf_prog_type_fuse 'constant', which cannot be
* constant until the code is upstreamed
*/
static ssize_t bpf_prog_type_fuse_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buff)
{
return sysfs_emit(buff, "%d\n", BPF_PROG_TYPE_FUSE);
}
static struct kobj_attribute bpf_prog_type_fuse_attr =
__ATTR_RO(bpf_prog_type_fuse);
static struct attribute *bpf_attributes[] = {
&bpf_prog_type_fuse_attr.attr,
NULL,
};
static const struct attribute_group bpf_attr_group = {
.attrs = bpf_attributes,
};
static const struct attribute_group *attribute_groups[] = {
&bpf_features_group,
&bpf_attr_group,
NULL
};
/* TODO remove to here */
static int fuse_sysfs_init(void)
{
int err;
@@ -1904,8 +2101,15 @@ static int fuse_sysfs_init(void)
if (err)
goto out_fuse_unregister;
/* TODO Remove when BPF_PROG_TYPE_FUSE is upstreamed */
err = sysfs_create_groups(fuse_kobj, attribute_groups);
if (err)
goto out_fuse_remove_mount_point;
return 0;
out_fuse_remove_mount_point:
sysfs_remove_mount_point(fuse_kobj, "connections");
out_fuse_unregister:
kobject_put(fuse_kobj);
out_err:
@@ -1914,6 +2118,7 @@ static int fuse_sysfs_init(void)
static void fuse_sysfs_cleanup(void)
{
sysfs_remove_groups(fuse_kobj, attribute_groups);
sysfs_remove_mount_point(fuse_kobj, "connections");
kobject_put(fuse_kobj);
}
@@ -1942,11 +2147,21 @@ static int __init fuse_init(void)
if (res)
goto err_sysfs_cleanup;
#ifdef CONFIG_FUSE_BPF
res = fuse_bpf_init();
if (res)
goto err_ctl_cleanup;
#endif
sanitize_global_limit(&max_user_bgreq);
sanitize_global_limit(&max_user_congthresh);
return 0;
#ifdef CONFIG_FUSE_BPF
err_ctl_cleanup:
fuse_ctl_cleanup();
#endif
err_sysfs_cleanup:
fuse_sysfs_cleanup();
err_dev_cleanup:
@@ -1964,6 +2179,9 @@ static void __exit fuse_exit(void)
fuse_ctl_cleanup();
fuse_sysfs_cleanup();
fuse_fs_cleanup();
#ifdef CONFIG_FUSE_BPF
fuse_bpf_cleanup();
#endif
fuse_dev_cleanup();
}

View File

@@ -34,7 +34,7 @@ static void fuse_file_accessed(struct file *dst_file, struct file *src_file)
touch_atime(&dst_file->f_path);
}
static void fuse_copyattr(struct file *dst_file, struct file *src_file)
void fuse_copyattr(struct file *dst_file, struct file *src_file)
{
struct inode *dst = file_inode(dst_file);
struct inode *src = file_inode(src_file);

View File

@@ -20,6 +20,8 @@ static bool fuse_use_readdirplus(struct inode *dir, struct dir_context *ctx)
if (!fc->do_readdirplus)
return false;
if (fi->nodeid == 0)
return false;
if (!fc->readdirplus_auto)
return true;
if (test_and_clear_bit(FUSE_I_ADVISE_RDPLUS, &fi->state))
@@ -579,6 +581,26 @@ int fuse_readdir(struct file *file, struct dir_context *ctx)
struct inode *inode = file_inode(file);
int err;
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
bool allow_force;
bool force_again = false;
bool is_continued = false;
again:
fer = fuse_bpf_backing(inode, struct fuse_read_io,
fuse_readdir_initialize, fuse_readdir_backing,
fuse_readdir_finalize,
file, ctx, &force_again, &allow_force, is_continued);
if (force_again && !IS_ERR(fer.result)) {
is_continued = true;
goto again;
}
if (fer.ret)
return PTR_ERR(fer.result);
#endif
if (fuse_is_bad(inode))
return -EIO;

View File

@@ -116,6 +116,17 @@ ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
struct fuse_getxattr_out outarg;
ssize_t ret;
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(inode, struct fuse_getxattr_io,
fuse_listxattr_initialize,
fuse_listxattr_backing, fuse_listxattr_finalize,
entry, list, size);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
if (fuse_is_bad(inode))
return -EIO;
@@ -184,6 +195,17 @@ static int fuse_xattr_get(const struct xattr_handler *handler,
struct dentry *dentry, struct inode *inode,
const char *name, void *value, size_t size)
{
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
fer = fuse_bpf_backing(inode, struct fuse_getxattr_io,
fuse_getxattr_initialize, fuse_getxattr_backing,
fuse_getxattr_finalize,
dentry, name, value, size);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
if (fuse_is_bad(inode))
return -EIO;
@@ -196,6 +218,24 @@ static int fuse_xattr_set(const struct xattr_handler *handler,
const char *name, const void *value, size_t size,
int flags)
{
#ifdef CONFIG_FUSE_BPF
struct fuse_err_ret fer;
if (value)
fer = fuse_bpf_backing(inode, struct fuse_setxattr_in,
fuse_setxattr_initialize, fuse_setxattr_backing,
fuse_setxattr_finalize, dentry, name, value,
size, flags);
else
fer = fuse_bpf_backing(inode, struct fuse_dummy_io,
fuse_removexattr_initialize,
fuse_removexattr_backing,
fuse_removexattr_finalize,
dentry, name);
if (fer.ret)
return PTR_ERR(fer.result);
#endif
if (fuse_is_bad(inode))
return -EIO;

View File

@@ -3,7 +3,6 @@
* Copyright 2019 Google LLC
*/
#include <linux/crc32.h>
#include <linux/delay.h>
#include <linux/file.h>
#include <linux/fsverity.h>
#include <linux/gfp.h>
@@ -1106,25 +1105,10 @@ static void notify_pending_reads(struct mount_info *mi,
wake_up_all(&mi->mi_blocks_written_notif_wq);
}
static int usleep_interruptible(u32 us)
{
/* See:
* https://www.kernel.org/doc/Documentation/timers/timers-howto.txt
* for explanation
*/
if (us < 10) {
udelay(us);
return 0;
} else if (us < 20000) {
usleep_range(us, us + us / 10);
return 0;
} else
return msleep_interruptible(us / 1000);
}
static int wait_for_data_block(struct data_file *df, int block_index,
struct data_file_block *res_block,
struct incfs_read_data_file_timeouts *timeouts)
struct incfs_read_data_file_timeouts *timeouts,
unsigned int *delayed_min_us)
{
struct data_file_block block = {};
struct data_file_segment *segment = NULL;
@@ -1132,7 +1116,7 @@ static int wait_for_data_block(struct data_file *df, int block_index,
struct mount_info *mi = NULL;
int error;
int wait_res = 0;
unsigned int delayed_pending_us = 0, delayed_min_us = 0;
unsigned int delayed_pending_us = 0;
bool delayed_pending = false;
if (!df || !res_block)
@@ -1163,8 +1147,7 @@ static int wait_for_data_block(struct data_file *df, int block_index,
if (is_data_block_present(&block)) {
*res_block = block;
if (timeouts && timeouts->min_time_us) {
delayed_min_us = timeouts->min_time_us;
error = usleep_interruptible(delayed_min_us);
*delayed_min_us = timeouts->min_time_us;
goto out;
}
return 0;
@@ -1211,13 +1194,9 @@ static int wait_for_data_block(struct data_file *df, int block_index,
delayed_pending = true;
delayed_pending_us = timeouts->max_pending_time_us -
jiffies_to_usecs(wait_res);
if (timeouts->min_pending_time_us > delayed_pending_us) {
delayed_min_us = timeouts->min_pending_time_us -
if (timeouts->min_pending_time_us > delayed_pending_us)
*delayed_min_us = timeouts->min_pending_time_us -
delayed_pending_us;
error = usleep_interruptible(delayed_min_us);
if (error)
return error;
}
error = down_read_killable(&segment->rwsem);
if (error)
@@ -1252,9 +1231,9 @@ static int wait_for_data_block(struct data_file *df, int block_index,
delayed_pending_us;
}
if (delayed_min_us) {
if (delayed_min_us && *delayed_min_us) {
mi->mi_reads_delayed_min++;
mi->mi_reads_delayed_min_us += delayed_min_us;
mi->mi_reads_delayed_min_us += *delayed_min_us;
}
return 0;
@@ -1284,7 +1263,8 @@ static int incfs_update_sysfs_error(struct file *file, int index, int result,
ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
int index, struct mem_range tmp,
struct incfs_read_data_file_timeouts *timeouts)
struct incfs_read_data_file_timeouts *timeouts,
unsigned int *delayed_min_us)
{
loff_t pos;
ssize_t result;
@@ -1303,7 +1283,8 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
mi = df->df_mount_info;
bfc = df->df_backing_file_context;
result = wait_for_data_block(df, index, &block, timeouts);
result = wait_for_data_block(df, index, &block, timeouts,
delayed_min_us);
if (result < 0)
goto out;
@@ -1381,7 +1362,8 @@ ssize_t incfs_read_merkle_tree_blocks(struct mem_range dst,
}
int incfs_process_new_data_block(struct data_file *df,
struct incfs_fill_block *block, u8 *data)
struct incfs_fill_block *block, u8 *data,
bool *complete)
{
struct mount_info *mi = NULL;
struct backing_file_context *bfc = NULL;
@@ -1420,27 +1402,42 @@ int incfs_process_new_data_block(struct data_file *df,
if (error)
return error;
if (is_data_block_present(&existing_block)) {
if (is_data_block_present(&existing_block))
/* Block is already present, nothing to do here */
return 0;
}
error = down_write_killable(&segment->rwsem);
if (error)
return error;
error = mutex_lock_interruptible(&bfc->bc_mutex);
if (!error) {
error = incfs_write_data_block_to_backing_file(
bfc, range(data, block->data_len), block->block_index,
df->df_blockmap_off, flags);
mutex_unlock(&bfc->bc_mutex);
}
if (!error) {
notify_pending_reads(mi, segment, block->block_index);
atomic_inc(&df->df_data_blocks_written);
}
/* Recheck inside write lock */
error = get_data_file_block(df, block->block_index, &existing_block);
if (error)
goto out_up_write;
if (is_data_block_present(&existing_block))
goto out_up_write;
error = mutex_lock_interruptible(&bfc->bc_mutex);
if (error)
goto out_up_write;
error = incfs_write_data_block_to_backing_file(bfc,
range(data, block->data_len), block->block_index,
df->df_blockmap_off, flags);
if (error)
goto out_mutex_unlock;
if (atomic_inc_return(&df->df_data_blocks_written)
>= df->df_data_block_count)
*complete = true;
out_mutex_unlock:
mutex_unlock(&bfc->bc_mutex);
if (!error)
notify_pending_reads(mi, segment, block->block_index);
out_up_write:
up_write(&segment->rwsem);
if (error)

View File

@@ -429,7 +429,8 @@ struct incfs_read_data_file_timeouts {
ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
int index, struct mem_range tmp,
struct incfs_read_data_file_timeouts *timeouts);
struct incfs_read_data_file_timeouts *timeouts,
unsigned int *delayed_min_us);
ssize_t incfs_read_merkle_tree_blocks(struct mem_range dst,
struct data_file *df, size_t offset);
@@ -441,7 +442,8 @@ int incfs_get_filled_blocks(struct data_file *df,
int incfs_read_file_signature(struct data_file *df, struct mem_range dst);
int incfs_process_new_data_block(struct data_file *df,
struct incfs_fill_block *block, u8 *data);
struct incfs_fill_block *block, u8 *data,
bool *complete);
int incfs_process_new_hash_block(struct data_file *df,
struct incfs_fill_block *block, u8 *data);

View File

@@ -33,11 +33,13 @@ static struct kobj_attribute name##_attr = __ATTR_RO(name)
DECLARE_FEATURE_FLAG(corefs);
DECLARE_FEATURE_FLAG(zstd);
DECLARE_FEATURE_FLAG(v2);
DECLARE_FEATURE_FLAG(bugfix_throttling);
static struct attribute *attributes[] = {
&corefs_attr.attr,
&zstd_attr.attr,
&v2_attr.attr,
&bugfix_throttling_attr.attr,
NULL,
};

View File

@@ -323,7 +323,7 @@ static int incfs_build_merkle_tree(struct file *f, struct data_file *df,
if (lvl == 0)
result = incfs_read_data_file_block(partial_buf,
f, i, tmp, NULL);
f, i, tmp, NULL, NULL);
else {
hash_level_offset = hash_offset +
hash_tree->hash_level_suboffset[lvl - 1];

View File

@@ -5,6 +5,7 @@
#include <linux/blkdev.h>
#include <linux/compat.h>
#include <linux/delay.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/fs_stack.h>
@@ -483,7 +484,8 @@ static struct dentry *open_or_create_special_dir(struct dentry *backing_dir,
static int read_single_page_timeouts(struct data_file *df, struct file *f,
int block_index, struct mem_range range,
struct mem_range tmp)
struct mem_range tmp,
unsigned int *delayed_min_us)
{
struct mount_info *mi = df->df_mount_info;
struct incfs_read_data_file_timeouts timeouts = {
@@ -515,7 +517,23 @@ static int read_single_page_timeouts(struct data_file *df, struct file *f,
}
return incfs_read_data_file_block(range, f, block_index, tmp,
&timeouts);
&timeouts, delayed_min_us);
}
static int usleep_interruptible(u32 us)
{
/* See:
* https://www.kernel.org/doc/Documentation/timers/timers-howto.txt
* for explanation
*/
if (us < 10) {
udelay(us);
return 0;
} else if (us < 20000) {
usleep_range(us, us + us / 10);
return 0;
} else
return msleep_interruptible(us / 1000);
}
static int read_single_page(struct file *f, struct page *page)
@@ -528,6 +546,7 @@ static int read_single_page(struct file *f, struct page *page)
int result = 0;
void *page_start;
int block_index;
unsigned int delayed_min_us = 0;
if (!df) {
SetPageError(page);
@@ -553,7 +572,8 @@ static int read_single_page(struct file *f, struct page *page)
bytes_to_read = min_t(loff_t, size - offset, PAGE_SIZE);
read_result = read_single_page_timeouts(df, f, block_index,
range(page_start, bytes_to_read), tmp);
range(page_start, bytes_to_read), tmp,
&delayed_min_us);
free_pages((unsigned long)tmp.data, get_order(tmp.len));
} else {
@@ -575,6 +595,8 @@ static int read_single_page(struct file *f, struct page *page)
flush_dcache_page(page);
kunmap(page);
unlock_page(page);
if (delayed_min_us)
usleep_interruptible(delayed_min_us);
return result;
}
@@ -668,8 +690,7 @@ static void notify_unlink(struct dentry *dentry, const char *file_id_str,
dput(file);
}
static void maybe_delete_incomplete_file(struct file *f,
struct data_file *df)
static void handle_file_completed(struct file *f, struct data_file *df)
{
struct backing_file_context *bfc;
struct mount_info *mi = df->df_mount_info;
@@ -678,9 +699,6 @@ static void maybe_delete_incomplete_file(struct file *f,
const struct cred *old_cred = override_creds(mi->mi_owner);
int error;
if (atomic_read(&df->df_data_blocks_written) < df->df_data_block_count)
goto out;
/* Truncate file to remove any preallocated space */
bfc = df->df_backing_file_context;
if (bfc) {
@@ -739,6 +757,7 @@ static long ioctl_fill_blocks(struct file *f, void __user *arg)
u8 *data_buf = NULL;
ssize_t error = 0;
int i = 0;
bool complete = false;
if (!df)
return -EBADF;
@@ -780,7 +799,7 @@ static long ioctl_fill_blocks(struct file *f, void __user *arg)
data_buf);
} else {
error = incfs_process_new_data_block(df, &fill_block,
data_buf);
data_buf, &complete);
}
if (error)
break;
@@ -789,7 +808,8 @@ static long ioctl_fill_blocks(struct file *f, void __user *arg)
if (data_buf)
free_pages((unsigned long)data_buf, get_order(data_buf_size));
maybe_delete_incomplete_file(f, df);
if (complete)
handle_file_completed(f, df);
/*
* Only report the error if no records were processed, otherwise

View File

@@ -79,6 +79,9 @@ BPF_PROG_TYPE(BPF_PROG_TYPE_LSM, lsm,
#endif
BPF_PROG_TYPE(BPF_PROG_TYPE_SYSCALL, bpf_syscall,
void *, void *)
#ifdef CONFIG_FUSE_BPF
BPF_PROG_TYPE(BPF_PROG_TYPE_FUSE, fuse, struct fuse_bpf_args, struct fuse_bpf_args)
#endif
BPF_MAP_TYPE(BPF_MAP_TYPE_ARRAY, array_map_ops)
BPF_MAP_TYPE(BPF_MAP_TYPE_PERCPU_ARRAY, percpu_array_map_ops)

View File

@@ -118,14 +118,14 @@ static inline int elf_core_copy_task_fpregs(struct task_struct *t, struct pt_reg
* Dumping its extra ELF program headers includes all the other information
* a debugger needs to easily find how the gate DSO was being used.
*/
extern Elf_Half elf_core_extra_phdrs(void);
extern Elf_Half elf_core_extra_phdrs(struct coredump_params *cprm);
extern int
elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset);
extern int
elf_core_write_extra_data(struct coredump_params *cprm);
extern size_t elf_core_extra_data_size(void);
extern size_t elf_core_extra_data_size(struct coredump_params *cprm);
#else
static inline Elf_Half elf_core_extra_phdrs(void)
static inline Elf_Half elf_core_extra_phdrs(struct coredump_params *cprm)
{
return 0;
}
@@ -140,7 +140,7 @@ static inline int elf_core_write_extra_data(struct coredump_params *cprm)
return 1;
}
static inline size_t elf_core_extra_data_size(void)
static inline size_t elf_core_extra_data_size(struct coredump_params *cprm)
{
return 0;
}

View File

@@ -73,6 +73,12 @@ static inline int eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n,
return -ENOSYS;
}
static inline int eventfd_signal_mask(struct eventfd_ctx *ctx, __u64 n,
unsigned mask)
{
return -ENOSYS;
}
static inline void eventfd_ctx_put(struct eventfd_ctx *ctx)
{

View File

@@ -156,6 +156,7 @@ struct hid_item {
#define HID_UP_DIGITIZER 0x000d0000
#define HID_UP_PID 0x000f0000
#define HID_UP_BATTERY 0x00850000
#define HID_UP_CAMERA 0x00900000
#define HID_UP_HPVENDOR 0xff7f0000
#define HID_UP_HPVENDOR2 0xff010000
#define HID_UP_MSVENDOR 0xff000000

View File

@@ -4476,7 +4476,7 @@ static inline u8 ieee80211_mle_common_size(const u8 *data)
return 0;
}
return common + mle->variable[0];
return sizeof(*mle) + common + mle->variable[0];
}
/**

View File

@@ -1379,6 +1379,9 @@ struct cfg80211_unsol_bcast_probe_resp {
* @fils_discovery: FILS discovery transmission parameters
* @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameters
* @mbssid_config: AP settings for multiple bssid
* @punct_bitmap: Preamble puncturing bitmap. Each bit represents
* a 20 MHz channel, lowest bit corresponding to the lowest channel.
* Bit set to 1 indicates that the channel is punctured.
*/
struct cfg80211_ap_settings {
struct cfg80211_chan_def chandef;
@@ -1413,6 +1416,7 @@ struct cfg80211_ap_settings {
struct cfg80211_fils_discovery fils_discovery;
struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp;
struct cfg80211_mbssid_config mbssid_config;
u16 punct_bitmap;
ANDROID_BACKPORT_RESERVED(1);
ANDROID_BACKPORT_RESERVED(2);
@@ -1444,6 +1448,9 @@ struct cfg80211_ap_settings {
* @radar_required: whether radar detection is required on the new channel
* @block_tx: whether transmissions should be blocked while changing
* @count: number of beacons until switch
* @punct_bitmap: Preamble puncturing bitmap. Each bit represents
* a 20 MHz channel, lowest bit corresponding to the lowest channel.
* Bit set to 1 indicates that the channel is punctured.
*/
struct cfg80211_csa_settings {
struct cfg80211_chan_def chandef;
@@ -1456,6 +1463,7 @@ struct cfg80211_csa_settings {
bool radar_required;
bool block_tx;
u8 count;
u16 punct_bitmap;
ANDROID_BACKPORT_RESERVED(1);
ANDROID_BACKPORT_RESERVED(2);
@@ -1979,6 +1987,24 @@ struct cfg80211_tid_stats {
* received packet with an FCS error matches the peer MAC address.
* @airtime_link_metric: mesh airtime link metric.
* @connected_to_as: true if mesh STA has a path to authentication server
* @mlo_params_valid: Indicates @assoc_link_id and @mld_addr fields are filled
* by driver. Drivers use this only in cfg80211_new_sta() calls when AP
* MLD's MLME/SME is offload to driver. Drivers won't fill this
* information in cfg80211_del_sta_sinfo(), get_station() and
* dump_station() callbacks.
* @assoc_link_id: Indicates MLO link ID of the AP, with which the station
* completed (re)association. This information filled for both MLO
* and non-MLO STA connections when the AP affiliated with an MLD.
* @mld_addr: For MLO STA connection, filled with MLD address of the station.
* For non-MLO STA connection, filled with all zeros.
* @assoc_resp_ies: IEs from (Re)Association Response.
* This is used only when in AP mode with drivers that do not use user
* space MLME/SME implementation. The information is provided only for the
* cfg80211_new_sta() calls to notify user space of the IEs. Drivers won't
* fill this information in cfg80211_del_sta_sinfo(), get_station() and
* dump_station() callbacks. User space needs this information to determine
* the accepted and rejected affiliated links of the connected station.
* @assoc_resp_ies_len: Length of @assoc_resp_ies buffer in octets.
*/
struct station_info {
u64 filled;
@@ -2039,6 +2065,12 @@ struct station_info {
u8 connected_to_as;
bool mlo_params_valid;
u8 assoc_link_id;
u8 mld_addr[ETH_ALEN] __aligned(2);
const u8 *assoc_resp_ies;
size_t assoc_resp_ies_len;
ANDROID_BACKPORT_RESERVED(1);
ANDROID_BACKPORT_RESERVED(2);
ANDROID_BACKPORT_RESERVED(3);
@@ -3803,6 +3835,17 @@ struct cfg80211_pmk_conf {
* the real status code for failures. Used only for the authentication
* response command interface (user space to driver).
* @pmkid: The identifier to refer a PMKSA.
* @mld_addr: MLD address of the peer. Used by the authentication request event
* interface. Driver indicates this to enable MLO during the authentication
* offload to user space. Driver shall look at %NL80211_ATTR_MLO_SUPPORT
* flag capability in NL80211_CMD_CONNECT to know whether the user space
* supports enabling MLO during the authentication offload.
* User space should use the address of the interface (on which the
* authentication request event reported) as self MLD address. User space
* and driver should use MLD addresses in RA, TA and BSSID fields of
* authentication frames sent or received via cfg80211. The driver
* translates the MLD addresses to/from link addresses based on the link
* chosen for the authentication.
*/
struct cfg80211_external_auth_params {
enum nl80211_external_auth_action action;
@@ -3811,6 +3854,7 @@ struct cfg80211_external_auth_params {
unsigned int key_mgmt_suite;
u16 status;
const u8 *pmkid;
u8 mld_addr[ETH_ALEN] __aligned(2);
ANDROID_BACKPORT_RESERVED(1);
ANDROID_BACKPORT_RESERVED(2);
@@ -4075,12 +4119,22 @@ struct cfg80211_pmsr_request {
* the IEs of the remote peer in the event from the host driver and
* the constructed IEs by the user space in the request interface.
* @ie_len: Length of IEs in octets.
* @assoc_link_id: MLO link ID of the AP, with which (re)association requested
* by peer. This will be filled by driver for both MLO and non-MLO station
* connections when the AP affiliated with an MLD. For non-MLD AP mode, it
* will be -1. Used only with OWE update event (driver to user space).
* @peer_mld_addr: For MLO connection, MLD address of the peer. For non-MLO
* connection, it will be all zeros. This is applicable only when
* @assoc_link_id is not -1, i.e., the AP affiliated with an MLD. Used only
* with OWE update event (driver to user space).
*/
struct cfg80211_update_owe_info {
u8 peer[ETH_ALEN] __aligned(2);
u16 status;
const u8 *ie;
size_t ie_len;
int assoc_link_id;
u8 peer_mld_addr[ETH_ALEN] __aligned(2);
ANDROID_BACKPORT_RESERVED(1);
ANDROID_BACKPORT_RESERVED(2);
@@ -4922,6 +4976,7 @@ struct cfg80211_ops {
* in order to not have them reachable in normal drivers, until we have
* complete feature/interface combinations/etc. advertisement. No driver
* should set this flag for now.
* @WIPHY_FLAG_SUPPORTS_EXT_KCK_32: The device supports 32-byte KCK keys.
*/
enum wiphy_flags {
WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK = BIT(0),
@@ -4934,7 +4989,7 @@ enum wiphy_flags {
WIPHY_FLAG_CONTROL_PORT_PROTOCOL = BIT(7),
WIPHY_FLAG_IBSS_RSN = BIT(8),
WIPHY_FLAG_MESH_AUTH = BIT(10),
/* use hole at 11 */
WIPHY_FLAG_SUPPORTS_EXT_KCK_32 = BIT(11),
/* use hole at 12 */
WIPHY_FLAG_SUPPORTS_FW_ROAM = BIT(13),
WIPHY_FLAG_AP_UAPSD = BIT(14),
@@ -8012,6 +8067,8 @@ void cfg80211_roamed(struct net_device *dev, struct cfg80211_roam_info *info,
*
* @dev: network device
* @bssid: the BSSID of the AP
* @td_bitmap: transition disable policy
* @td_bitmap_len: Length of transition disable policy
* @gfp: allocation flags
*
* This function should be called by a driver that supports 4 way handshake
@@ -8022,7 +8079,7 @@ void cfg80211_roamed(struct net_device *dev, struct cfg80211_roam_info *info,
* indicate the 802.11 association.
*/
void cfg80211_port_authorized(struct net_device *dev, const u8 *bssid,
gfp_t gfp);
const u8* td_bitmap, u8 td_bitmap_len, gfp_t gfp);
/**
* cfg80211_disconnected - notify cfg80211 that connection was dropped
@@ -8607,13 +8664,14 @@ bool cfg80211_reg_can_beacon_relax(struct wiphy *wiphy,
* @dev: the device which switched channels
* @chandef: the new channel definition
* @link_id: the link ID for MLO, must be 0 for non-MLO
* @punct_bitmap: the new puncturing bitmap
*
* Caller must acquire wdev_lock, therefore must only be called from sleepable
* driver context!
*/
void cfg80211_ch_switch_notify(struct net_device *dev,
struct cfg80211_chan_def *chandef,
unsigned int link_id);
unsigned int link_id, u16 punct_bitmap);
/*
* cfg80211_ch_switch_started_notify - notify channel switch start
@@ -8622,6 +8680,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
* @link_id: the link ID for MLO, must be 0 for non-MLO
* @count: the number of TBTTs until the channel switch happens
* @quiet: whether or not immediate quiet was requested by the AP
* @punct_bitmap: the future puncturing bitmap
*
* Inform the userspace about the channel switch that has just
* started, so that it can take appropriate actions (eg. starting
@@ -8630,7 +8689,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
void cfg80211_ch_switch_started_notify(struct net_device *dev,
struct cfg80211_chan_def *chandef,
unsigned int link_id, u8 count,
bool quiet);
bool quiet, u16 punct_bitmap);
/**
* ieee80211_operating_class_to_band - convert operating class to band
@@ -9244,4 +9303,16 @@ static inline int cfg80211_color_change_notify(struct net_device *dev)
0, 0);
}
/**
* cfg80211_valid_disable_subchannel_bitmap - validate puncturing bitmap
* @bitmap: bitmap to be validated
* @chandef: channel definition
*
* Validate the puncturing bitmap.
*
* Return: %true if the bitmap is valid. %false otherwise.
*/
bool cfg80211_valid_disable_subchannel_bitmap(u16 *bitmap,
const struct cfg80211_chan_def *chandef);
#endif /* __NET_CFG80211_H */

View File

@@ -43,10 +43,6 @@ DECLARE_HOOK(android_vh_binder_wait_for_work,
DECLARE_HOOK(android_vh_sync_txn_recvd,
TP_PROTO(struct task_struct *tsk, struct task_struct *from),
TP_ARGS(tsk, from));
DECLARE_RESTRICTED_HOOK(android_rvh_binder_transaction,
TP_PROTO(struct binder_proc *target_proc, struct binder_proc *proc,
struct binder_thread *thread, struct binder_transaction_data *tr),
TP_ARGS(target_proc, proc, thread, tr), 1);
DECLARE_HOOK(android_vh_binder_proc_transaction_entry,
TP_PROTO(struct binder_proc *proc, struct binder_transaction *t,
struct binder_thread **thread, int node_debug_id, bool pending_async,

Some files were not shown because too many files have changed in this diff Show More