Merge branch 'android13-5.15' into android13-5.15-lts
Sync up with android13-5.15 for the following commits: *5476e160a6Merge "Merge tag 'android13-5.15.94_r00' into android13-5.15" into android13-5.15 |\ | *5155624549Merge tag 'android13-5.15.94_r00' into android13-5.15 * |e5862f1a40UPSTREAM: wifi: nl80211: fix puncturing bitmap policy |/ *f8c9753a12UPSTREAM: hwrng: virtio - add an internal buffer *1dddc1992eANDROID: GKI: Update abi_gki_aarch64_qcom *092199e995BACKPORT: wifi: nl80211: Allow authentication frames and set keys on NAN interface *05164a8564UPSTREAM: wifi: cfg80211: Allow action frames to be transmitted with link BSS in MLD *6bab8a4002BACKPORT: wifi: cfg80211: include puncturing bitmap in channel switch events *e8a4772f4dBACKPORT: wifi: nl80211: validate and configure puncturing bitmap *b099f1eb0bUPSTREAM: regmap: Don't warn about cache only mode for devices with no cache *b3ebd7ca3bANDROID: dma-buf: system_heap: kmap_local_page instead of kmap_atomic *16e9875abdANDROID: GKI: update xiaomi symbol list *cf18e5eb5eUPSTREAM: ext4: fix another off-by-one fsmap error on 1k block filesystems *090c1ebf8dUPSTREAM: dm verity: stop using WQ_UNBOUND for verify_wq *7f356bba02BACKPORT: dm verity: enable WQ_HIGHPRI on verify_wq *4017ffbb86UPSTREAM: dm verity: remove WQ_CPU_INTENSIVE flag since using WQ_UNBOUND *a6c4727f6aUPSTREAM: loop: Fix use-after-free issues *24c1fcb787ANDROID: GKI: Update symbol list for mtk *6c60fdbac2UPSTREAM: ext4: block range must be validated before use in ext4_mb_clear_bb() *53ce0eef46UPSTREAM: ext4: add strict range checks while freeing blocks *20389d86cbUPSTREAM: ext4: add ext4_sb_block_valid() refactored out of ext4_inode_block_valid() *60c24f4d15UPSTREAM: ext4: refactor ext4_free_blocks() to pull out ext4_mb_clear_bb() *7ba7908a8dANDROID: mm: handle SPF using a copy of the original vma *521f3bc70dANDROID: mm: fix UAF in SPF *e09118b90bANDROID: GKI: Update symbol list for mtk *0659efffd9UPSTREAM: arm64: efi: Make efi_rt_lock a raw_spinlock *6b908238a8UPSTREAM: wifi: cfg80211: Set SSID if it is not already set *554a967167Revert "Revert "ANDROID: usb: dwc3: gadget: don't cancel the started requests"" *eef9e1295bUPSTREAM: rtmutex: Ensure that the top waiter is always woken up *cc0db0b28cUPSTREAM: cgroup/cpuset: Don't filter offline CPUs in cpuset_cpus_allowed() for top cpuset tasks *3c4f884306UPSTREAM: ext4: refuse to create ea block when umounted *0473082f7aUPSTREAM: ext4: optimize ea_inode block expansion *bf0b8e8181UPSTREAM: ext4: allocate extended attribute value in vmalloc area *79bd2581b8ANDROID: ABI: Update the GKI symbol list and ABI XML *cfe5bd7f01ANDROID: abi_gki_aarch64_qcom: Update symbol list *f3091267acANDROID: GKI: update xiaomi symbol list *fb1db47637UPSTREAM: Partially revert "perf/arm-cmn: Optimise DTC counter accesses" *1f12217e5dUPSTREAM: usb: dwc3: gadget: Ignore End Transfer delay on teardown *fc41b9e122UPSTREAM: elfcore: Add a cprm parameter to elf_core_extra_{phdrs,data_size} *ee863e2109UPSTREAM: arm64: mte: Fix double-freeing of the temporary tag storage during coredump *7dc85abaacUPSTREAM: wifi: nl80211: Add checks for nla_nest_start() in nl80211_send_iface() *8b1316dd5bUPSTREAM: mm/page_exit: fix kernel doc warning in page_ext_put() *37fbaa232dUPSTREAM: f2fs: fix gc mode when gc_urgent_high_remaining is 1 *ad8cc978ccBACKPORT: mm: multi-gen LRU: move lru_gen_add_mm() out of IRQ-off region *73d24f728fUPSTREAM: KVM: arm64: Use correct accessor to parse stage-1 PTEs *2f6641fde7UPSTREAM: wifi: fix multi-link element subelement iteration *0cc04953f0UPSTREAM: perf/arm-cmn: Add more bits to child node address offset field *a481cc4587UPSTREAM: perf/arm-cmn: Update watchpoint format *668c43092bUPSTREAM: perf/arm-cmn: Hide XP PUB events for CMN-600 *5761541a4eBACKPORT: wifi: cfg80211: move puncturing bitmap validation from mac80211 *267de69e07UPSTREAM: wifi: nl80211: add MLO_LINK_ID to CMD_STOP_AP event *83e77c3183BACKPORT: cfg80211: Update Transition Disable policy during port authorization *f4559cb666ANDROID: ABI: Update db845c symbol list on ufshcd *bef41f506fANDROID: usb: gadget: f_accessory: update to usb_gstrings_attach *0fd1c2a78dUPSTREAM: usb: gadget: composite: Draw 100mA current if not configured *a223191ed9UPSTREAM: usb: dwc3: gadget: Change condition for processing suspend event *91c677412cUPSTREAM: net/sched: tcindex: update imperfect hash filters respecting rcu *6ca9fd3a0cBACKPORT: FROMGIT: scsi: ufs: core: Add hibernation callbacks *35d26a7736ANDROID: ABI: Update unisoc thermal symbol list *683fe954dcANDROID: thermal: Add a vendor hook for thermal throttle update *e013dc7081ANDROID: GKI: Add symbol list for Lenovo *6a7aa09013ANDROID: Enable percpu high priority kthreads for erofs *40a9ba963bUPSTREAM: erofs: fix an error code in z_erofs_init_zip_subsystem() *7dc188b222BACKPORT: erofs: add per-cpu threads for decompression as an option *4fd62a87f5ANDROID: ABI: Update oplus symbol list *05b5ff11adANDROID: vendor_hooks: Add hooks for mutex and rwsem optimistic spin *9eec95bb4bUPSTREAM: io_uring: ensure that io_init_req() passes in the right issue_flags *c112dc5771ANDROID: Update the GKI symbol list and ABI XML *bdf1c2ccdfUPSTREAM: io_uring: add missing lock in io_get_file_fixed *3352886caeANDROID: gki_config: enable CONFIG_IIO_TRIGGERED_BUFFER *e21e3d108bANDROID: GKI: VIVO: Add a symbol to symbol list *5239ef3d19UPSTREAM: drivers/thermal/cpufreq_cooling: Use private callback ops for each cooling device *287c9980a0UPSTREAM: scsi: scsi_debug: Fix possible UAF in sdebug_add_host_helper() *6db5181a3fUPSTREAM: io_uring/rw: remove leftover debug statement *4390be5c79UPSTREAM: io_uring/rw: ensure kiocb_end_write() is always called *6b3d1f961dUPSTREAM: io_uring: fix double poll leak on repolling *3749f8d826UPSTREAM: io_uring: Clean up a false-positive warning from GCC 9.3.0 *0da7ee3fbeUPSTREAM: io_uring/net: fix fast_iov assignment in io_setup_async_msg() *3a4f67f903UPSTREAM: io_uring: io_kiocb_update_pos() should not touch file for non -1 offset *3c83e0a95aUPSTREAM: io_uring/rw: defer fsnotify calls to task context *630c372219UPSTREAM: io_uring: do not recalculate ppos unnecessarily *47179f7dd8UPSTREAM: io_uring: update kiocb->ki_pos at execution time *b0b3d93abcUPSTREAM: io_uring: remove duplicated calls to io_kiocb_ppos *7b865f60c7UPSTREAM: io_uring: ensure that cached task references are always put on exit *c72cbb2252UPSTREAM: io_uring: fix async accept on O_NONBLOCK sockets *88be697dc0UPSTREAM: io_uring: allow re-poll if we made progress *393d994594UPSTREAM: io_uring: support MSG_WAITALL for IORING_OP_SEND(MSG) *8f3a4070fdUPSTREAM: io_uring: add flag for disabling provided buffer recycling *b0b6bfe443UPSTREAM: io_uring: ensure recv and recvmsg handle MSG_WAITALL correctly *40520bb96cUPSTREAM: io_uring: improve send/recv error handling *6c0dd68dbeUPSTREAM: io_uring: pass in EPOLL_URING_WAKE for eventfd signaling and wakeups *ab6956ac6bUPSTREAM: eventfd: provide a eventfd_signal_mask() helper *b4ab4ac900UPSTREAM: eventpoll: add EPOLL_URING_WAKE poll wakeup flag *2373a0c72fUPSTREAM: io_uring: don't gate task_work run on TIF_NOTIFY_SIGNAL *b579578d93UPSTREAM: io_uring/io-wq: only free worker if it was allocated for creation *19758f54f7UPSTREAM: io_uring/io-wq: free worker if task_work creation is canceled *65e1f2ef67UPSTREAM: io_uring: lock overflowing for IOPOLL *198e5002e2UPSTREAM: io_uring: Fix unsigned 'res' comparison with zero in io_fixup_rw_res() *5af453ff63UPSTREAM: io_uring: fix CQ waiting timeout handling *e6f9c1b71aUPSTREAM: io_uring: check for valid register opcode earlier *dcc1ea1639UPSTREAM: io_uring: Fix a null-ptr-deref in io_tctx_exit_cb() *3a1c153b96UPSTREAM: io_uring: move to separate directory *c0dee08111UPSTREAM: io_uring/poll: fix poll_refs race with cancelation *5a5dcf5c1dUPSTREAM: io_uring: make poll refs more robust *30909f865bUPSTREAM: io_uring: cmpxchg for poll arm refs release *242ed49852UPSTREAM: io_uring: fix tw losing poll events *7e603b2079UPSTREAM: io_uring: update res mask in io_poll_check_events *fab4d02938UPSTREAM: wifi: cfg80211: Extend cfg80211_update_owe_info_event() for MLD AP *048ad5d375UPSTREAM: wifi: cfg80211: Extend cfg80211_new_sta() for MLD AP *9216110fdfUPSTREAM: wifi: cfg80211: Authentication offload to user space for MLO connection in STA mode *272c5a9d37UPSTREAM: wifi: cfg80211: trace: remove MAC_PR_{FMT,ARG} *99da8df376UPSTREAM: KVM: VMX: Execute IBPB on emulated VM-exit when guest has IBRS *16bb33d7efANDROID: ABI: Update allowed list for QCOM *3383d21e9eUPSTREAM: wifi: cfg80211: Support 32 bytes KCK key in GTK rekey offload *26bac3f093ANDROID: MGLRU: Don't skip anon reclaim if swap low *151bc21658ANDROID: incremental fs: Move throttling to outside page lock *3ab6fda925ANDROID: incremental fs: Fix race between truncate and write last block *aba5f5754bANDROID: fuse-bpf: Do not change bpf program in lookups *dd72bb259fUPSTREAM: usb: gadget: u_serial: Add null pointer check in gserial_resume *a2ee0d8df3UPSTREAM: binder: Gracefully handle BINDER_TYPE_FDA objects with num_fds=0 *9cdb4e5812UPSTREAM: binder: Address corner cases in deferred copy and fixup *884fec935cUPSTREAM: binder: fix pointer cast warning *0502554803UPSTREAM: binder: defer copies of pre-patched txn data *a9afae9aa4UPSTREAM: binder: read pre-translated fds from sender buffer *7887b13e6bUPSTREAM: net_sched: reject TCF_EM_SIMPLE case for complex ematch module *89eccb8495UPSTREAM: ext4: add inode table check in __ext4_get_inode_loc to aovid possible infinite loop *fda78dabcaRevert "ANDROID: GKI: Add vendor hook to binder transaction" *c404b74d5fANDROID: GKI: Update the ABI xml representation for fuse-bpf *7a1cca7dbdANDROID: fuse-bpf: Add /sys/fs flags for fuse-bpf version *f5f4199c10ANDROID: fuse-bpf v1.1 *bff9debefdANDROID: GKI: update xiaomi symbol list *5a6502af11ANDROID: psi: Add vendor hooks for PSI tracing *af8dfb011fFROMLIST: input: Add KEY_CAMERA_FOCUS event in HID *79b3761c89BACKPORT: sched/core: Fix use-after-free bug in dup_user_cpus_ptr() *a838fd5d08Revert "FROMGIT: sched: Add __releases annotations to affine_move_task()" *5767bdca07Revert "BACKPORT: FROMGIT: sched: Introduce affinity_context" *158d54a8a8Revert "BACKPORT: FROMGIT: sched: Always preserve the user requested cpumask" *92bd55bc52Revert "FROMLIST: sched: Fix use-after-free bug in dup_user_cpus_ptr()" *bd82038474Revert "BACKPORT: FROMGIT: sched: Enforce user requested affinity" *0f54a1c923Revert "FROMGIT: sched: Always clear user_cpus_ptr in do_set_cpus_allowed()" *97c7d8de1dRevert "ANDROID: sched: Keep sched_class::set_cpus_allowed stable" *4ef9aa1b49Revert "ANDROID: sched: Move scratch_mask to a percpu variable" *aa27279666BACKPORT: of: reserved_mem: Have kmemleak ignore dynamically allocated reserved mem *20c1f0a6d2Revert "BACKPORT: FROMGIT: mm/cma.c: make kmemleak aware of all CMA regions" *5862eafd8eRevert "FROMGIT: mm/cma.c: delete kmemleak objects when freeing CMA areas to buddy at boot" *5c6418ddeeRevert "UPSTREAM: mm: kmemleak: alloc gray object for reserved region with direct map" *45a51d2eb8ANDROID: GKI: Update symbol list for Amlogic *d41e54aefbANDROID: GKI: Add symbol list for ZEKU *32d4e80df4ANDROID: dm-bow: Add ABI documentation *88e27b17aaANDROID: dm-bow: Fix 5.15 compatibility issue *63a1e5f1d0Revert "ANDROID: dm-bow: remove dm-bow" *d07a013cd0ANDROID: vendor_hook: fix the error record of rwsem *5fcf93b316ANDROID: ABI: Update allowed list for QCOM *16e7178e58ANDROID: GKI: Update abi_gki_aarch64_qcom symbols *4ef0a7dff1ANDROID: crypto: testmgr - add back deleted hctr2 test vectors *2cde0330aaANDROID: abi_gki_aarch64_qcom: Add rpmsg_rx_done and zap_vma_ptes *810133cb61ANDROID: cpuidle-psci: Fix suspicious RCU usage *6f810b08efFROMGIT: usb: gadget: configfs: Restrict symlink creation is UDC already binded *9dff37ba7bANDROID: Update symbol list for sunxi *18eaf71786FROMGIT: scsi: ufs: Try harder to change the power mode *cfc314cd6fUPSTREAM: scsi: ufs: Reduce the START STOP UNIT timeout *6a9193a0ffUPSTREAM: 9p/fd: fix issue of list_del corruption in p9_fd_cancel() *b4c3ac4720UPSTREAM: fs: do not update freeing inode i_io_list *b607fae900UPSTREAM: f2fs: fix to invalidate dcc->f2fs_issue_discard in error path *0b34c91b83FROMGIT: wifi: cfg80211: Fix extended KCK key length check in nl80211_set_rekey_data() *f719d33f11UPSTREAM: iommu/iova: Fix alloc iova overflows issue *43c604d36eUPSTREAM: iommu: Avoid races around device probe *613751d732ANDROID: GKI: Update abi_gki_aarch64_pasa *2f7c6eb587ANDROID: softirq: Refine RT defer softirq *286300ece4UPSTREAM: wifi: wilc1000: validate number of channels *7594f016edUPSTREAM: wifi: wilc1000: validate pairwise and authentication suite offsets *d9a54ce812UPSTREAM: wifi: wilc1000: validate length of IEEE80211_P2P_ATTR_OPER_CHANNEL attribute *0be0985947UPSTREAM: media: dvb-core: Fix UAF due to refcount races at releasing *e5905d8ab3ANDROID: Update the GKI symbol list and ABI XML *984241bdc0UPSTREAM: efi: rt-wrapper: Add missing include *ec6fe82350UPSTREAM: arm64: efi: Execute runtime services from a dedicated stack *003dacfceeUPSTREAM: KVM: x86/mmu: Fix race condition in direct_page_fault *19987d1e7fUPSTREAM: usb: gadget: uvc: Rename bmInterfaceFlags -> bmInterlaceFlags *6d2ec81c11ANDROID: GKI: KASAN: disable INLINE *ae0a1eb830ANDROID: GKI: Update symbol list for mtk *9a8dcea6abANDROID: usb: f_accessory: Check buffer size when initialised via composite *2a298e88ebUPSTREAM: drm/shmem-helper: Avoid vm_open error paths *2c76d2b9c5UPSTREAM: proc: avoid integer type confusion in get_proc_long *cc6c5c7fa2UPSTREAM: ALSA: pcm: Move rwsem lock inside snd_ctl_elem_read to prevent UAF *0861407d6eUPSTREAM: proc: proc_skip_spaces() shouldn't think it is working on C strings *3cf30601b0UPSTREAM: usb: gadget: f_hid: fix f_hidg lifetime vs cdev *8864b0342fUPSTREAM: nfp: fix use-after-free in area_cache_get() *9563d28619FROMGIT: scsi: ufs: Modify Tactive time setting conditions *afe869b80aANDROID: gki_defconfig: disable various x86 and hw flags *4dc28fe928UPSTREAM: 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:
@@ -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 = {
|
||||
|
||||
@@ -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
|
||||
|
||||
19
Documentation/ABI/testing/dm-bow
Normal file
19
Documentation/ABI/testing/dm-bow
Normal 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
|
||||
19
Documentation/ABI/testing/sysfs-fs-fuse
Normal file
19
Documentation/ABI/testing/sysfs-fs-fuse
Normal 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
|
||||
|
||||
@@ -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>
|
||||
|
||||
99
Documentation/device-mapper/dm-bow.txt
Normal file
99
Documentation/device-mapper/dm-bow.txt
Normal 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.
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
956
android/abi_gki_aarch64_lenovo
Normal file
956
android/abi_gki_aarch64_lenovo
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -14,3 +14,5 @@
|
||||
hid_report_raw_event
|
||||
hid_unregister_driver
|
||||
hidinput_calc_abs_res
|
||||
iio_trigger_generic_data_rdy_poll
|
||||
input_device_enabled
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -335,6 +335,7 @@
|
||||
del_gendisk
|
||||
del_timer
|
||||
del_timer_sync
|
||||
dentry_path_raw
|
||||
destroy_workqueue
|
||||
dev_alloc_name
|
||||
dev_coredumpm
|
||||
|
||||
@@ -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
1262
android/abi_gki_aarch64_zeku
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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 \
|
||||
|
||||
1536
crypto/testmgr.h
1536
crypto/testmgr.h
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
1309
drivers/md/dm-bow.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
188
fs/erofs/zdata.c
188
fs/erofs/zdata.c
@@ -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]);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
19
fs/f2fs/gc.c
19
fs/f2fs/gc.c
@@ -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());
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
2473
fs/fuse/backing.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
528
fs/fuse/dir.c
528
fs/fuse/dir.c
@@ -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 = {
|
||||
|
||||
130
fs/fuse/file.c
130
fs/fuse/file.c
@@ -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;
|
||||
|
||||
|
||||
717
fs/fuse/fuse_i.h
717
fs/fuse/fuse_i.h
@@ -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 */
|
||||
|
||||
356
fs/fuse/inode.c
356
fs/fuse/inode.c
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user