android_kernel_motorola_sm6375/fs/aio.c
Michael Bestas 73abf253d5
Merge tag 'ASB-2024-06-05_11-5.4' of https://android.googlesource.com/kernel/common into android13-5.4-lahaina
https://source.android.com/docs/security/bulletin/2024-06-01
CVE-2024-26926

* tag 'ASB-2024-06-05_11-5.4' of https://android.googlesource.com/kernel/common:
  ANDROID: ABI fixup for abi break in struct dst_ops
  BACKPORT: net: fix __dst_negative_advice() race
  UPSTREAM: selftests: timers: Fix valid-adjtimex signed left-shift undefined behavior
  Revert "timers: Rename del_timer_sync() to timer_delete_sync()"
  Reapply "media: ttpci: fix two memleaks in budget_av_attach"
  Revert "media: rename VFL_TYPE_GRABBER to _VIDEO"
  Revert "media: media/pci: rename VFL_TYPE_GRABBER to _VIDEO"
  Revert "media: ttpci: fix two memleaks in budget_av_attach"
  Revert "net: ip_tunnel: make sure to pull inner header in ip_tunnel_rcv()"
  Revert "regmap: allow to define reg_update_bits for no bus configuration"
  Revert "regmap: Add bulk read/write callbacks into regmap_config"
  Revert "serial: max310x: fix IO data corruption in batched operations"
  Revert "geneve: make sure to pull inner header in geneve_rx()"
  Linux 5.4.274
  firmware: meson_sm: fix to avoid potential NULL pointer dereference
  ip_gre: do not report erspan version on GRE interface
  erspan: Check IFLA_GRE_ERSPAN_VER is set.
  VMCI: Fix possible memcpy() run-time warning in vmci_datagram_invoke_guest_handler()
  Bluetooth: btintel: Fixe build regression
  x86/alternative: Don't call text_poke() in lazy TLB mode
  drm/i915/gt: Reset queue_priority_hint on parking
  x86/mm/pat: fix VM_PAT handling in COW mappings
  virtio: reenable config if freezing device failed
  drm/vkms: call drm_atomic_helper_shutdown before drm_dev_put()
  tty: n_gsm: require CAP_NET_ADMIN to attach N_GSM0710 ldisc
  netfilter: nf_tables: discard table flag update with pending basechain deletion
  netfilter: nf_tables: release mutex after nft_gc_seq_end from abort path
  netfilter: nf_tables: release batch on table validation from abort path
  netfilter: nf_tables: reject new basechain after table flag update
  fbmon: prevent division by zero in fb_videomode_from_videomode()
  fbdev: viafb: fix typo in hw_bitblt_1 and hw_bitblt_2
  usb: sl811-hcd: only defined function checkdone if QUIRK2 is defined
  usb: typec: tcpci: add generic tcpci fallback compatible
  tools: iio: replace seekdir() in iio_generic_buffer
  ktest: force $buildonly = 1 for 'make_warnings_file' test type
  Input: allocate keycode for Display refresh rate toggle
  block: prevent division by zero in blk_rq_stat_sum()
  Revert "ACPI: PM: Block ASUS B1400CEAE from suspend to idle by default"
  SUNRPC: increase size of rpc_wait_queue.qlen from unsigned short to unsigned int
  drm/amd/display: Fix nanosec stat overflow
  media: sta2x11: fix irq handler cast
  isofs: handle CDs with bad root inode but good Joliet root directory
  scsi: lpfc: Fix possible memory leak in lpfc_rcv_padisc()
  sysv: don't call sb_bread() with pointers_lock held
  Input: synaptics-rmi4 - fail probing if memory allocation for "phys" fails
  Bluetooth: btintel: Fix null ptr deref in btintel_read_version
  btrfs: send: handle path ref underflow in header iterate_inode_ref()
  btrfs: export: handle invalid inode or root reference in btrfs_get_parent()
  btrfs: handle chunk tree lookup error in btrfs_relocate_sys_chunks()
  tools/power x86_energy_perf_policy: Fix file leak in get_pkg_num()
  ionic: set adminq irq affinity
  arm64: dts: rockchip: fix rk3399 hdmi ports node
  arm64: dts: rockchip: fix rk3328 hdmi ports node
  panic: Flush kernel log buffer at the end
  VMCI: Fix memcpy() run-time warning in dg_dispatch_as_host()
  wifi: ath9k: fix LNA selection in ath_ant_try_scan()
  s390/entry: align system call table on 8 bytes
  x86/mce: Make sure to grab mce_sysfs_mutex in set_bank()
  ALSA: hda/realtek: Update Panasonic CF-SZ6 quirk to support headset with microphone
  ata: sata_mv: Fix PCI device ID table declaration compilation warning
  scsi: mylex: Fix sysfs buffer lengths
  ata: sata_sx4: fix pdc20621_get_from_dimm() on 64-bit
  ASoC: ops: Fix wraparound for mask in snd_soc_get_volsw
  net: ravb: Always process TX descriptor ring
  erspan: make sure erspan_base_hdr is present in skb->head
  erspan: Add type I version 0 support.
  init: open /initrd.image with O_LARGEFILE
  initramfs: switch initramfs unpacking to struct file based APIs
  fs: add a vfs_fchmod helper
  fs: add a vfs_fchown helper
  staging: vc04_services: fix information leak in create_component()
  staging: vc04_services: changen strncpy() to strscpy_pad()
  staging: mmal-vchiq: Fix client_component for 64 bit kernel
  staging: mmal-vchiq: Allocate and free components as required
  i40e: fix vf may be used uninitialized in this function warning
  ipv6: Fix infinite recursion in fib6_dump_done().
  selftests: reuseaddr_conflict: add missing new line at the end of the output
  net: stmmac: fix rx queue priority assignment
  net/sched: act_skbmod: prevent kernel-infoleak
  bpf, sockmap: Prevent lock inversion deadlock in map delete elem
  netfilter: nf_tables: Fix potential data-race in __nft_flowtable_type_get()
  netfilter: nf_tables: flush pending destroy work before exit_net release
  mm, vmscan: prevent infinite loop for costly GFP_NOIO | __GFP_RETRY_MAYFAIL allocations
  Revert "x86/mm/ident_map: Use gbpages only where full GB page should be mapped."
  vfio/platform: Create persistent IRQ handlers
  vfio/pci: Create persistent INTx handler
  vfio: Introduce interface to flush virqfd inject workqueue
  vfio/pci: Lock external INTx masking ops
  vfio/pci: Disable auto-enable of exclusive INTx IRQ
  net/rds: fix possible cp null dereference
  netfilter: nf_tables: disallow timeout for anonymous sets
  Bluetooth: Fix TOCTOU in HCI debugfs implementation
  Bluetooth: hci_event: set the conn encrypted before conn establishes
  x86/cpufeatures: Add new word for scattered features
  r8169: fix issue caused by buggy BIOS on certain boards with RTL8168d
  dm integrity: fix out-of-range warning
  tcp: properly terminate timers for kernel sockets
  ixgbe: avoid sleeping allocation in ixgbe_ipsec_vf_add_sa()
  nfc: nci: Fix uninit-value in nci_dev_up and nci_ntf_packet
  USB: core: Fix deadlock in usb_deauthorize_interface()
  scsi: lpfc: Correct size for wqe for memset()
  x86/cpu: Enable STIBP on AMD if Automatic IBRS is enabled
  scsi: qla2xxx: Fix command flush on cable pull
  usb: udc: remove warning when queue disabled ep
  usb: dwc2: gadget: LPM flow fix
  usb: dwc2: host: Fix ISOC flow in DDMA mode
  usb: dwc2: host: Fix hibernation flow
  usb: dwc2: host: Fix remote wakeup from hibernation
  scsi: core: Fix unremoved procfs host directory regression
  ALSA: sh: aica: reorder cleanup operations to avoid UAF bugs
  usb: cdc-wdm: close race between read and workqueue
  mmc: core: Avoid negative index with array access
  mmc: core: Initialize mmc_blk_ioc_data
  exec: Fix NOMMU linux_binprm::exec in transfer_args_to_stack()
  wifi: mac80211: check/clear fast rx for non-4addr sta VLAN changes
  mm/migrate: set swap entry values of THP tail pages properly.
  mm/memory-failure: fix an incorrect use of tail pages
  vt: fix memory overlapping when deleting chars in the buffer
  bounds: support non-power-of-two CONFIG_NR_CPUS
  powerpc: xor_vmx: Add '-mhard-float' to CFLAGS
  efivarfs: Request at most 512 bytes for variable names
  perf/core: Fix reentry problem in perf_output_read_group()
  loop: loop_set_status_from_info() check before assignment
  loop: Check for overflow while configuring loop
  loop: Factor out configuring loop from status
  loop: Refactor loop_set_status() size calculation
  loop: Factor out setting loop device size
  loop: Remove sector_t truncation checks
  loop: Call loop_config_discard() only after new config is applied
  Revert "loop: Check for overflow while configuring loop"
  btrfs: allocate btrfs_ioctl_defrag_range_args on stack
  printk: Update @console_may_schedule in console_trylock_spinning()
  xen/events: close evtchn after mapping cleanup
  x86/speculation: Support intra-function call validation
  objtool: Add support for intra-function calls
  objtool: is_fentry_call() crashes if call has no destination
  fs/aio: Check IOCB_AIO_RW before the struct aio_kiocb conversion
  vt: fix unicode buffer corruption when deleting characters
  tty: serial: fsl_lpuart: avoid idle preamble pending if CTS is enabled
  usb: port: Don't try to peer unused USB ports based on location
  usb: gadget: ncm: Fix handling of zero block length packets
  USB: usb-storage: Prevent divide-by-0 error in isd200_ata_command
  ALSA: hda/realtek - Fix headset Mic no show at resume back for Lenovo ALC897 platform
  xfrm: Avoid clang fortify warning in copy_to_user_tmpl()
  netfilter: nf_tables: reject constant set with timeout
  netfilter: nf_tables: disallow anonymous set with timeout flag
  netfilter: nf_tables: mark set as dead when unbinding anonymous set with timeout
  comedi: comedi_test: Prevent timers rescheduling during deletion
  dm snapshot: fix lockup in dm_exception_table_exit
  ahci: asm1064: asm1166: don't limit reported ports
  ahci: asm1064: correct count of reported ports
  x86/CPU/AMD: Update the Zenbleed microcode revisions
  nilfs2: prevent kernel bug at submit_bh_wbc()
  nilfs2: use a more common logging style
  nilfs2: fix failure to detect DAT corruption in btree and direct mappings
  memtest: use {READ,WRITE}_ONCE in memory scanning
  drm/vc4: hdmi: do not return negative values from .get_modes()
  drm/imx/ipuv3: do not return negative values from .get_modes()
  drm/exynos: do not return negative values from .get_modes()
  s390/zcrypt: fix reference counting on zcrypt card objects
  soc: fsl: qbman: Use raw spinlock for cgr_lock
  soc: fsl: qbman: Add CGR update function
  soc: fsl: qbman: Add helper for sanity checking cgr ops
  soc: fsl: qbman: Always disable interrupts when taking cgr_lock
  ring-buffer: Fix full_waiters_pending in poll
  ring-buffer: Fix resetting of shortest_full
  vfio/platform: Disable virqfds on cleanup
  kbuild: Move -Wenum-{compare-conditional,enum-conversion} into W=1
  speakup: Fix 8bit characters from direct synth
  slimbus: core: Remove usage of the deprecated ida_simple_xx() API
  nvmem: meson-efuse: fix function pointer type mismatch
  firmware: meson_sm: Rework driver as a proper platform driver
  ext4: fix corruption during on-line resize
  hwmon: (amc6821) add of_match table
  mmc: core: Fix switch on gp3 partition
  dm-raid: fix lockdep waring in "pers->hot_add_disk"
  Revert "Revert "md/raid5: Wait for MD_SB_CHANGE_PENDING in raid5d""
  PCI/PM: Drain runtime-idle callbacks before driver removal
  PCI: Drop pci_device_remove() test of pci_dev->driver
  btrfs: fix off-by-one chunk length calculation at contains_pending_extent()
  fuse: don't unhash root
  mmc: tmio: avoid concurrent runs of mmc_request_done()
  PM: sleep: wakeirq: fix wake irq warning in system suspend
  USB: serial: cp210x: add pid/vid for TDK NC0110013M and MM0110113M
  USB: serial: option: add MeiG Smart SLM320 product
  USB: serial: cp210x: add ID for MGP Instruments PDS100
  USB: serial: add device ID for VeriFone adapter
  USB: serial: ftdi_sio: add support for GMC Z216C Adapter IR-USB
  powerpc/fsl: Fix mfpmr build errors with newer binutils
  clk: qcom: mmcc-msm8974: fix terminating of frequency table arrays
  clk: qcom: mmcc-apq8084: fix terminating of frequency table arrays
  clk: qcom: gcc-ipq8074: fix terminating of frequency table arrays
  PM: suspend: Set mem_sleep_current during kernel command line setup
  parisc: Strip upper 32 bit of sum in csum_ipv6_magic for 64-bit builds
  parisc: Fix csum_ipv6_magic on 64-bit systems
  parisc: Fix csum_ipv6_magic on 32-bit systems
  parisc: Fix ip_fast_csum
  parisc: Do not hardcode registers in checksum functions
  mtd: rawnand: meson: fix scrambling mode value in command macro
  ubi: correct the calculation of fastmap size
  ubi: Check for too small LEB size in VTBL code
  ubifs: Set page uptodate in the correct place
  fat: fix uninitialized field in nostale filehandles
  ext4: correct best extent lstart adjustment logic
  selftests/mqueue: Set timeout to 180 seconds
  crypto: qat - resolve race condition during AER recovery
  crypto: qat - fix double free during reset
  sparc: vDSO: fix return value of __setup handler
  sparc64: NMI watchdog: fix return value of __setup handler
  KVM: Always flush async #PF workqueue when vCPU is being destroyed
  media: xc4000: Fix atomicity violation in xc4000_get_frequency
  serial: max310x: fix NULL pointer dereference in I2C instantiation
  arm: dts: marvell: Fix maxium->maxim typo in brownstone dts
  ARM: dts: mmp2-brownstone: Don't redeclare phandle references
  smack: Handle SMACK64TRANSMUTE in smack_inode_setsecurity()
  smack: Set SMACK64TRANSMUTE only for dirs in smack_inode_setxattr()
  clk: qcom: gcc-sdm845: Add soft dependency on rpmhpd
  media: staging: ipu3-imgu: Set fields before media_entity_pads_init()
  wifi: brcmfmac: Fix use-after-free bug in brcmf_cfg80211_detach
  timers: Rename del_timer_sync() to timer_delete_sync()
  timers: Use del_timer_sync() even on UP
  timers: Update kernel-doc for various functions
  x86/bugs: Use sysfs_emit()
  x86/cpu: Support AMD Automatic IBRS
  Documentation/hw-vuln: Update spectre doc
  amdkfd: use calloc instead of kzalloc to avoid integer overflow
  Linux 5.4.273
  regmap: Add missing map->bus check
  spi: spi-mt65xx: Fix NULL pointer access in interrupt handler
  bpf: report RCU QS in cpumap kthread
  rcu: add a helper to report consolidated flavor QS
  netfilter: nf_tables: do not compare internal table flags on updates
  ARM: dts: sun8i-h2-plus-bananapi-m2-zero: add regulator nodes vcc-dram and vcc1v2
  octeontx2-af: Use separate handlers for interrupts
  net/bnx2x: Prevent access to a freed page in page_pool
  hsr: Handle failures in module init
  rds: introduce acquire/release ordering in acquire/release_in_xmit()
  packet: annotate data-races around ignore_outgoing
  hsr: Fix uninit-value access in hsr_get_node()
  s390/vtime: fix average steal time calculation
  octeontx2-af: Use matching wake_up API variant in CGX command interface
  usb: gadget: net2272: Use irqflags in the call to net2272_probe_fin
  staging: greybus: fix get_channel_from_mode() failure path
  serial: 8250_exar: Don't remove GPIO device on suspend
  rtc: mt6397: select IRQ_DOMAIN instead of depending on it
  kconfig: fix infinite loop when expanding a macro at the end of file
  tty: serial: samsung: fix tx_empty() to return TIOCSER_TEMT
  serial: max310x: fix syntax error in IRQ error message
  tty: vt: fix 20 vs 0x20 typo in EScsiignore
  afs: Revert "afs: Hide silly-rename files from userspace"
  NFS: Fix an off by one in root_nfs_cat()
  watchdog: stm32_iwdg: initialize default timeout
  net: sunrpc: Fix an off by one in rpc_sockaddr2uaddr()
  scsi: bfa: Fix function pointer type mismatch for hcb_qe->cbfn
  RDMA/device: Fix a race between mad_client and cm_client init
  scsi: csiostor: Avoid function pointer casts
  ALSA: usb-audio: Stop parsing channels bits when all channels are found.
  clk: Fix clk_core_get NULL dereference
  sparc32: Fix section mismatch in leon_pci_grpci
  backlight: lp8788: Fully initialize backlight_properties during probe
  backlight: lm3639: Fully initialize backlight_properties during probe
  backlight: da9052: Fully initialize backlight_properties during probe
  backlight: lm3630a: Don't set bl->props.brightness in get_brightness
  backlight: lm3630a: Initialize backlight_properties on init
  powerpc/embedded6xx: Fix no previous prototype for avr_uart_send() etc.
  drm/msm/dpu: add division of drm_display_mode's hskew parameter
  powerpc/hv-gpci: Fix the H_GET_PERF_COUNTER_INFO hcall return value checks
  drm/mediatek: Fix a null pointer crash in mtk_drm_crtc_finish_page_flip
  media: ttpci: fix two memleaks in budget_av_attach
  media: media/pci: rename VFL_TYPE_GRABBER to _VIDEO
  media: rename VFL_TYPE_GRABBER to _VIDEO
  media: v4l2-core: correctly validate video and metadata ioctls
  media: go7007: fix a memleak in go7007_load_encoder
  media: dvb-frontends: avoid stack overflow warnings with clang
  media: pvrusb2: fix uaf in pvr2_context_set_notify
  drm/amdgpu: Fix missing break in ATOM_ARG_IMM Case of atom_get_src_int()
  ASoC: meson: axg-tdm-interface: fix mclk setup without mclk-fs
  mtd: rawnand: lpc32xx_mlc: fix irq handler prototype
  mtd: maps: physmap-core: fix flash size larger than 32-bit
  crypto: arm/sha - fix function cast warnings
  mfd: altera-sysmgr: Call of_node_put() only when of_parse_phandle() takes a ref
  mfd: syscon: Call of_node_put() only when of_parse_phandle() takes a ref
  drm/tegra: put drm_gem_object ref on error in tegra_fb_create
  clk: hisilicon: hi3519: Release the correct number of gates in hi3519_clk_unregister()
  PCI: Mark 3ware-9650SE Root Port Extended Tags as broken
  drm/mediatek: dsi: Fix DSI RGB666 formats and definitions
  clk: qcom: dispcc-sdm845: Adjust internal GDSC wait times
  media: pvrusb2: fix pvr2_stream_callback casts
  media: pvrusb2: remove redundant NULL check
  media: go7007: add check of return value of go7007_read_addr()
  media: imx: csc/scaler: fix v4l2_ctrl_handler memory leak
  perf stat: Avoid metric-only segv
  ALSA: seq: fix function cast warnings
  drm/radeon/ni: Fix wrong firmware size logging in ni_init_microcode()
  perf thread_map: Free strlist on normal path in thread_map__new_by_tid_str()
  PCI: switchtec: Fix an error handling path in switchtec_pci_probe()
  quota: Fix rcu annotations of inode dquot pointers
  quota: Fix potential NULL pointer dereference
  quota: simplify drop_dquot_ref()
  clk: qcom: reset: Ensure write completion on reset de/assertion
  clk: qcom: reset: Commonize the de/assert functions
  clk: qcom: reset: support resetting multiple bits
  clk: qcom: reset: Allow specifying custom reset delay
  media: edia: dvbdev: fix a use-after-free
  media: v4l2-mem2mem: fix a memleak in v4l2_m2m_register_entity
  media: v4l2-tpg: fix some memleaks in tpg_alloc
  media: em28xx: annotate unchecked call to media_device_register()
  perf evsel: Fix duplicate initialization of data->id in evsel__parse_sample()
  drm/amd/display: Fix potential NULL pointer dereferences in 'dcn10_set_output_transfer_func()'
  perf record: Fix possible incorrect free in record__switch_output()
  PCI/DPC: Print all TLP Prefixes, not just the first
  media: tc358743: register v4l2 async device only after successful setup
  dmaengine: tegra210-adma: Update dependency to ARCH_TEGRA
  drm/rockchip: lvds: do not overwrite error code
  drm: Don't treat 0 as -1 in drm_fixp2int_ceil
  drm/rockchip: inno_hdmi: Fix video timing
  drm/tegra: output: Fix missing i2c_put_adapter() in the error handling paths of tegra_output_probe()
  drm/tegra: dsi: Fix missing pm_runtime_disable() in the error handling path of tegra_dsi_probe()
  drm/tegra: dsi: Fix some error handling paths in tegra_dsi_probe()
  drm/tegra: dsi: Make use of the helper function dev_err_probe()
  gpu: host1x: mipi: Update tegra_mipi_request() to be node based
  drm/tegra: dsi: Add missing check for of_find_device_by_node
  dm: call the resume method on internal suspend
  dm raid: fix false positive for requeue needed during reshape
  nfp: flower: handle acti_netdevs allocation failure
  net/x25: fix incorrect parameter validation in the x25_getsockopt() function
  net: kcm: fix incorrect parameter validation in the kcm_getsockopt) function
  udp: fix incorrect parameter validation in the udp_lib_getsockopt() function
  l2tp: fix incorrect parameter validation in the pppol2tp_getsockopt() function
  tcp: fix incorrect parameter validation in the do_tcp_getsockopt() function
  net: hns3: fix port duplex configure error in IMP reset
  net: ip_tunnel: make sure to pull inner header in ip_tunnel_rcv()
  ipv6: fib6_rules: flush route cache when rule is changed
  bpf: Fix stackmap overflow check on 32-bit arches
  bpf: Fix hashtab overflow check on 32-bit arches
  sr9800: Add check for usbnet_get_endpoints
  Bluetooth: hci_core: Fix possible buffer overflow
  Bluetooth: Remove superfluous call to hci_conn_check_pending()
  igb: Fix missing time sync events
  igb: move PEROUT and EXTTS isr logic to separate functions
  mmc: wmt-sdmmc: remove an incorrect release_mem_region() call in the .remove function
  SUNRPC: fix some memleaks in gssx_dec_option_array
  x86, relocs: Ignore relocations in .notes section
  ACPI: scan: Fix device check notification handling
  ARM: dts: imx6dl-yapp4: Move the internal switch PHYs under the switch node
  ARM: dts: imx6dl-yapp4: Fix typo in the QCA switch register address
  ARM: dts: imx6dl-yapp4: Move phy reset into switch node
  ARM: dts: arm: realview: Fix development chip ROM compatible value
  net: ena: Remove ena_select_queue
  net: ena: cosmetic: fix line break issues
  wifi: brcmsmac: avoid function pointer casts
  iommu/amd: Mark interrupt as managed
  bus: tegra-aconnect: Update dependency to ARCH_TEGRA
  ACPI: processor_idle: Fix memory leak in acpi_processor_power_exit()
  arm64: dts: qcom: msm8996: Pad addresses
  arm64: dts: qcom: msm8996: Move regulator consumers to db820c
  arm64: dts: qcom: msm8996: Use node references in db820c
  arm64: dts: qcom: db820c: Move non-soc entries out of /soc
  bpf: Mark bpf_spin_{lock,unlock}() helpers with notrace correctly
  bpf: Factor out bpf_spin_lock into helpers.
  bpf: Add typecast to bpf helpers to help BTF generation
  arm64: dts: mediatek: mt7622: add missing "device_type" to memory nodes
  wifi: libertas: fix some memleaks in lbs_allocate_cmd_buffer()
  net: blackhole_dev: fix build warning for ethh set but not used
  af_unix: Annotate data-race of gc_in_progress in wait_for_unix_gc().
  sock_diag: annotate data-races around sock_diag_handlers[family]
  wifi: mwifiex: debugfs: Drop unnecessary error check for debugfs_create_dir()
  wifi: wilc1000: fix RCU usage in connect path
  wifi: wilc1000: fix declarations ordering
  wifi: b43: Disable QoS for bcm4331
  wifi: b43: Stop correct queue in DMA worker when QoS is disabled
  b43: main: Fix use true/false for bool type
  wifi: b43: Stop/wake correct queue in PIO Tx path when QoS is disabled
  wifi: b43: Stop/wake correct queue in DMA Tx path when QoS is disabled
  b43: dma: Fix use true/false for bool type variable
  wifi: ath10k: fix NULL pointer dereference in ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev()
  timekeeping: Fix cross-timestamp interpolation for non-x86
  timekeeping: Fix cross-timestamp interpolation corner case decision
  timekeeping: Fix cross-timestamp interpolation on counter wrap
  aoe: fix the potential use-after-free problem in aoecmd_cfg_pkts
  fs/select: rework stack allocation hack for clang
  nbd: null check for nla_nest_start
  do_sys_name_to_handle(): use kzalloc() to fix kernel-infoleak
  ASoC: wm8962: Fix up incorrect error message in wm8962_set_fll
  ASoC: wm8962: Enable both SPKOUTR_ENA and SPKOUTL_ENA in mono mode
  ASoC: wm8962: Enable oscillator if selecting WM8962_FLL_OSC
  Input: gpio_keys_polled - suppress deferred probe error for gpio
  ASoC: Intel: bytcr_rt5640: Add an extra entry for the Chuwi Vi8 tablet
  firewire: core: use long bus reset on gap count error
  Bluetooth: rfcomm: Fix null-ptr-deref in rfcomm_check_security
  scsi: mpt3sas: Prevent sending diag_reset when the controller is ready
  btrfs: fix data race at btrfs_use_block_rsv() when accessing block reserve
  dm-verity, dm-crypt: align "struct bvec_iter" correctly
  block: sed-opal: handle empty atoms when parsing response
  parisc/ftrace: add missing CONFIG_DYNAMIC_FTRACE check
  net/iucv: fix the allocation size of iucv_path_table array
  RDMA/mlx5: Relax DEVX access upon modify commands
  HID: multitouch: Add required quirk for Synaptics 0xcddc device
  MIPS: Clear Cause.BD in instruction_pointer_set
  x86/xen: Add some null pointer checking to smp.c
  ASoC: rt5645: Make LattePanda board DMI match more precise
  selftests: tls: use exact comparison in recv_partial
  io_uring: drop any code related to SCM_RIGHTS
  io_uring/unix: drop usage of io_uring socket
  UPSTREAM: arm64: dts: qcom: sdm845: fix USB DP/DM HS PHY interrupts
  UPSTREAM: arm64: dts: qcom: add PDC interrupt controller for SDM845
  Linux 5.4.272
  arm64: dts: qcom: sdm845: fix USB DP/DM HS PHY interrupts
  arm64: dts: qcom: add PDC interrupt controller for SDM845
  serial: max310x: fix IO data corruption in batched operations
  serial: max310x: implement I2C support
  serial: max310x: make accessing revision id interface-agnostic
  regmap: Add bulk read/write callbacks into regmap_config
  regmap: allow to define reg_update_bits for no bus configuration
  serial: max310x: Unprepare and disable clock in error path
  getrusage: use sig->stats_lock rather than lock_task_sighand()
  getrusage: use __for_each_thread()
  getrusage: move thread_group_cputime_adjusted() outside of lock_task_sighand()
  getrusage: add the "signal_struct *sig" local variable
  y2038: rusage: use __kernel_old_timeval
  hv_netvsc: Register VF in netvsc_probe if NET_DEVICE_REGISTER missed
  hv_netvsc: use netif_is_bond_master() instead of open code
  hv_netvsc: Make netvsc/VF binding check both MAC and serial number
  Input: i8042 - fix strange behavior of touchpad on Clevo NS70PU
  serial: max310x: prevent infinite while() loop in port startup
  serial: max310x: use a separate regmap for each port
  serial: max310x: use regmap methods for SPI batch operations
  serial: max310x: Make use of device properties
  serial: max310x: fail probe if clock crystal is unstable
  serial: max310x: Try to get crystal clock rate from property
  serial: max310x: Use devm_clk_get_optional() to get the input clock
  um: allow not setting extra rpaths in the linux binary
  selftests: mm: fix map_hugetlb failure on 64K page size systems
  netrom: Fix data-races around sysctl_net_busy_read
  netrom: Fix a data-race around sysctl_netrom_link_fails_count
  netrom: Fix a data-race around sysctl_netrom_routing_control
  netrom: Fix a data-race around sysctl_netrom_transport_no_activity_timeout
  netrom: Fix a data-race around sysctl_netrom_transport_requested_window_size
  netrom: Fix a data-race around sysctl_netrom_transport_busy_delay
  netrom: Fix a data-race around sysctl_netrom_transport_acknowledge_delay
  netrom: Fix a data-race around sysctl_netrom_transport_maximum_tries
  netrom: Fix a data-race around sysctl_netrom_transport_timeout
  netrom: Fix data-races around sysctl_netrom_network_ttl_initialiser
  netrom: Fix a data-race around sysctl_netrom_obsolescence_count_initialiser
  netrom: Fix a data-race around sysctl_netrom_default_path_quality
  netfilter: nf_conntrack_h323: Add protection for bmp length out of range
  netfilter: nft_ct: fix l3num expectations with inet pseudo family
  net/rds: fix WARNING in rds_conn_connect_if_down
  net/ipv6: avoid possible UAF in ip6_route_mpath_notify()
  net: ice: Fix potential NULL pointer dereference in ice_bridge_setlink()
  geneve: make sure to pull inner header in geneve_rx()
  ixgbe: {dis, en}able irqs in ixgbe_txrx_ring_{dis, en}able
  net: lan78xx: fix runtime PM count underflow on link stop
  lan78xx: Fix race conditions in suspend/resume handling
  lan78xx: Fix partial packet errors on suspend/resume
  lan78xx: Add missing return code checks
  lan78xx: Fix white space and style issues
  Linux 5.4.271
  gpio: 74x164: Enable output pins after registers are reset
  fs,hugetlb: fix NULL pointer dereference in hugetlbs_fill_super
  cachefiles: fix memory leak in cachefiles_add_cache()
  x86/cpu/intel: Detect TME keyid bits before setting MTRR mask registers
  mmc: core: Fix eMMC initialization with 1-bit bus connection
  dmaengine: fsl-qdma: init irq after reg initialization
  dmaengine: fsl-qdma: fix SoC may hang on 16 byte unaligned read
  btrfs: dev-replace: properly validate device names
  wifi: nl80211: reject iftype change with mesh ID change
  gtp: fix use-after-free and null-ptr-deref in gtp_newlink()
  afs: Fix endless loop in directory parsing
  ALSA: Drop leftover snd-rtctimer stuff from Makefile
  power: supply: bq27xxx-i2c: Do not free non existing IRQ
  efi/capsule-loader: fix incorrect allocation size
  rtnetlink: fix error logic of IFLA_BRIDGE_FLAGS writing back
  netfilter: nf_tables: allow NFPROTO_INET in nft_(match/target)_validate()
  Bluetooth: Enforce validation on max value of connection interval
  Bluetooth: hci_event: Fix handling of HCI_EV_IO_CAPA_REQUEST
  Bluetooth: Avoid potential use-after-free in hci_error_reset
  net: usb: dm9601: fix wrong return value in dm9601_mdio_read
  lan78xx: enable auto speed configuration for LAN7850 if no EEPROM is detected
  ipv6: fix potential "struct net" leak in inet6_rtm_getaddr()
  tun: Fix xdp_rxq_info's queue_index when detaching
  net: ip_tunnel: prevent perpetual headroom growth
  netlink: Fix kernel-infoleak-after-free in __skb_datagram_iter
  ANDROID: GKI: update .xml file due to USB changes in 5.4.270
  Revert "bpf: Add map and need_defer parameters to .map_fd_put_ptr()"
  Revert "hrtimer: Report offline hrtimer enqueue"
  Revert "drm/mipi-dsi: Fix detach call without attach"
  Linux 5.4.270
  scripts/bpf: Fix xdp_md forward declaration typo
  fs/aio: Restrict kiocb_set_cancel_fn() to I/O submitted via libaio
  drm/syncobj: call drm_syncobj_fence_add_wait when WAIT_AVAILABLE flag is set
  drm/syncobj: make lockdep complain on WAIT_FOR_SUBMIT v3
  netfilter: nf_tables: set dormant flag on hook register failure
  tls: stop recv() if initial process_rx_list gave us non-DATA
  tls: rx: drop pointless else after goto
  tls: rx: jump to a more appropriate label
  s390: use the correct count for __iowrite64_copy()
  packet: move from strlcpy with unused retval to strscpy
  ipv6: sr: fix possible use-after-free and null-ptr-deref
  afs: Increase buffer size in afs_update_volume_status()
  ipv6: properly combine dev_base_seq and ipv6.dev_addr_genid
  ipv4: properly combine dev_base_seq and ipv4.dev_addr_genid
  nouveau: fix function cast warnings
  scsi: jazz_esp: Only build if SCSI core is builtin
  bpf, scripts: Correct GPL license name
  scripts/bpf: teach bpf_helpers_doc.py to dump BPF helper definitions
  RDMA/srpt: fix function pointer cast warnings
  RDMA/srpt: Make debug output more detailed
  RDMA/bnxt_re: Return error for SRQ resize
  IB/hfi1: Fix a memleak in init_credit_return
  usb: roles: don't get/set_role() when usb_role_switch is unregistered
  usb: gadget: ncm: Avoid dropping datagrams of properly parsed NTBs
  usb: cdns3: fix memory double free when handle zero packet
  usb: cdns3: fixed memory use after free at cdns3_gadget_ep_disable()
  ARM: ep93xx: Add terminator to gpiod_lookup_table
  l2tp: pass correct message length to ip6_append_data
  PCI/MSI: Prevent MSI hardware interrupt number truncation
  gtp: fix use-after-free and null-ptr-deref in gtp_genl_dump_pdp()
  dm-crypt: don't modify the data when using authenticated encryption
  IB/hfi1: Fix sdma.h tx->num_descs off-by-one error
  PCI: tegra: Fix OF node reference leak
  PCI: tegra: Fix reporting GPIO error value
  arm64: dts: qcom: msm8916: Fix typo in pronto remoteproc node
  drm/amdgpu: Fix type of second parameter in trans_msg() callback
  iomap: Set all uptodate bits for an Uptodate page
  dm-integrity: don't modify bio's immutable bio_vec in integrity_metadata()
  x86/alternatives: Disable KASAN in apply_alternatives()
  drm/amdgpu: Check for valid number of registers to read
  Revert "drm/sun4i: dsi: Change the start delay calculation"
  ALSA: hda/realtek - Enable micmute LED on and HP system
  selftests/bpf: Avoid running unprivileged tests with alignment requirements
  net: bridge: clear bridge's private skb space on xmit
  spi: mt7621: Fix an error message in mt7621_spi_probe()
  pinctrl: rockchip: Fix refcount leak in rockchip_pinctrl_parse_groups
  pinctrl: pinctrl-rockchip: Fix a bunch of kerneldoc misdemeanours
  tcp: add annotations around sk->sk_shutdown accesses
  tcp: return EPOLLOUT from tcp_poll only when notsent_bytes is half the limit
  tcp: factor out __tcp_close() helper
  pmdomain: renesas: r8a77980-sysc: CR7 must be always on
  s390/qeth: Fix potential loss of L3-IP@ in case of network issues
  virtio-blk: Ensure no requests in virtqueues before deleting vqs.
  firewire: core: send bus reset promptly on gap count error
  scsi: lpfc: Use unsigned type for num_sge
  hwmon: (coretemp) Enlarge per package core count limit
  nvmet-fc: abort command when there is no binding
  netfilter: conntrack: check SCTP_CID_SHUTDOWN_ACK for vtag setting in sctp_new
  ASoC: sunxi: sun4i-spdif: Add support for Allwinner H616
  nvmet-tcp: fix nvme tcp ida memory leak
  regulator: pwm-regulator: Add validity checks in continuous .get_voltage
  ext4: avoid allocating blocks from corrupted group in ext4_mb_find_by_goal()
  ext4: avoid allocating blocks from corrupted group in ext4_mb_try_best_found()
  ahci: add 43-bit DMA address quirk for ASMedia ASM1061 controllers
  ahci: asm1166: correct count of reported ports
  fbdev: sis: Error out if pixclock equals zero
  fbdev: savage: Error out if pixclock equals zero
  wifi: mac80211: fix race condition on enabling fast-xmit
  wifi: cfg80211: fix missing interfaces when dumping
  dmaengine: fsl-qdma: increase size of 'irq_name'
  dmaengine: shdma: increase size of 'dev_id'
  scsi: target: core: Add TMF to tmr_list handling
  sched/rt: Disallow writing invalid values to sched_rt_period_us
  sched/rt: Fix sysctl_sched_rr_timeslice intial value
  userfaultfd: fix mmap_changing checking in mfill_atomic_hugetlb
  nilfs2: replace WARN_ONs for invalid DAT metadata block requests
  memcg: add refcnt for pcpu stock to avoid UAF problem in drain_all_stock()
  sched/rt: sysctl_sched_rr_timeslice show default timeslice after reset
  net/sched: Retire dsmark qdisc
  net/sched: Retire ATM qdisc
  net/sched: Retire CBQ qdisc
  KVM: arm64: vgic-its: Test for valid IRQ in MOVALL handler
  KVM: arm64: vgic-its: Test for valid IRQ in its_sync_lpi_pending_table()
  Linux 5.4.269
  of: gpio unittest kfree() wrong object
  of: unittest: fix EXPECT text for gpio hog errors
  net: bcmgenet: Fix EEE implementation
  Revert "Revert "mtd: rawnand: gpmi: Fix setting busy timeout setting""
  netfilter: nf_tables: fix pointer math issue in nft_byteorder_eval()
  lsm: new security_file_ioctl_compat() hook
  drm/msm/dsi: Enable runtime PM
  PM: runtime: Have devm_pm_runtime_enable() handle pm_runtime_dont_use_autosuspend()
  PM: runtime: add devm_pm_runtime_enable helper
  nilfs2: fix potential bug in end_buffer_async_write
  sched/membarrier: reduce the ability to hammer on sys_membarrier
  net: prevent mss overflow in skb_segment()
  netfilter: ipset: Missing gc cancellations fixed
  netfilter: ipset: fix performance regression in swap operation
  KVM: arm64: vgic-its: Avoid potential UAF in LPI translation cache
  mips: Fix max_mapnr being uninitialized on early stages
  arch, mm: remove stale mentions of DISCONIGMEM
  bus: moxtet: Add spi device table
  Revert "md/raid5: Wait for MD_SB_CHANGE_PENDING in raid5d"
  tracing: Inform kmemleak of saved_cmdlines allocation
  pmdomain: core: Move the unused cleanup to a _sync initcall
  can: j1939: Fix UAF in j1939_sk_match_filter during setsockopt(SO_J1939_FILTER)
  irqchip/irq-brcmstb-l2: Add write memory barrier before exit
  nfp: flower: prevent re-adding mac index for bonded port
  nfp: use correct macro for LengthSelect in BAR config
  nilfs2: fix hang in nilfs_lookup_dirty_data_buffers()
  nilfs2: fix data corruption in dsync block recovery for small block sizes
  ALSA: hda/conexant: Add quirk for SWS JS201D
  mmc: slot-gpio: Allow non-sleeping GPIO ro
  x86/mm/ident_map: Use gbpages only where full GB page should be mapped.
  x86/Kconfig: Transmeta Crusoe is CPU family 5, not 6
  serial: max310x: improve crystal stable clock detection
  serial: max310x: set default value when reading clock ready bit
  ring-buffer: Clean ring_buffer_poll_wait() error return
  iio: magnetometer: rm3100: add boundary check for the value read from RM3100_REG_TMRC
  staging: iio: ad5933: fix type mismatch regression
  tracing: Fix wasted memory in saved_cmdlines logic
  ext4: fix double-free of blocks due to wrong extents moved_len
  misc: fastrpc: Mark all sessions as invalid in cb_remove
  binder: signal epoll threads of self-work
  ALSA: hda/realtek: Enable headset mic on Vaio VJFE-ADL
  xen-netback: properly sync TX responses
  nfc: nci: free rx_data_reassembly skb on NCI device cleanup
  kbuild: Fix changing ELF file type for output of gen_btf for big endian
  firewire: core: correct documentation of fw_csr_string() kernel API
  scsi: Revert "scsi: fcoe: Fix potential deadlock on &fip->ctlr_lock"
  i2c: i801: Fix block process call transactions
  i2c: i801: Remove i801_set_block_buffer_mode
  usb: f_mass_storage: forbid async queue when shutdown happen
  USB: hub: check for alternate port before enabling A_ALT_HNP_SUPPORT
  HID: wacom: Do not register input devices until after hid_hw_start
  HID: wacom: generic: Avoid reporting a serial of '0' to userspace
  mm/writeback: fix possible divide-by-zero in wb_dirty_limits(), again
  tracing/trigger: Fix to return error if failed to alloc snapshot
  i40e: Fix waiting for queues of all VSIs to be disabled
  MIPS: Add 'memory' clobber to csum_ipv6_magic() inline assembler
  ASoC: rt5645: Fix deadlock in rt5645_jack_detect_work()
  spi: ppc4xx: Drop write-only variable
  of: unittest: Fix compile in the non-dynamic case
  of: unittest: add overlay gpio test to catch gpio hog problem
  btrfs: send: return EOPNOTSUPP on unknown flags
  btrfs: forbid deleting live subvol qgroup
  btrfs: forbid creating subvol qgroups
  netfilter: nft_set_rbtree: skip end interval element from gc
  net: stmmac: xgmac: fix a typo of register name in DPP safety handling
  net: stmmac: xgmac: use #define for string constants
  vhost: use kzalloc() instead of kmalloc() followed by memset()
  Input: atkbd - skip ATKBD_CMD_SETLEDS when skipping ATKBD_CMD_GETID
  hrtimer: Report offline hrtimer enqueue
  USB: serial: cp210x: add ID for IMST iM871A-USB
  USB: serial: option: add Fibocom FM101-GL variant
  USB: serial: qcserial: add new usb-id for Dell Wireless DW5826e
  net/af_iucv: clean up a try_then_request_module()
  netfilter: nft_ct: reject direction for ct id
  netfilter: nft_compat: restrict match/target protocol to u16
  netfilter: nft_compat: reject unused compat flag
  ppp_async: limit MRU to 64K
  tipc: Check the bearer type before calling tipc_udp_nl_bearer_add()
  rxrpc: Fix response to PING RESPONSE ACKs to a dead call
  inet: read sk->sk_family once in inet_recv_error()
  hwmon: (coretemp) Fix bogus core_id to attr name mapping
  hwmon: (coretemp) Fix out-of-bounds memory access
  hwmon: (aspeed-pwm-tacho) mutex for tach reading
  atm: idt77252: fix a memleak in open_card_ubr0
  selftests: net: avoid just another constant wait
  net: stmmac: xgmac: fix handling of DPP safety error for DMA channels
  phy: ti: phy-omap-usb2: Fix NULL pointer dereference for SRP
  dmaengine: fix is_slave_direction() return false when DMA_DEV_TO_DEV
  phy: renesas: rcar-gen3-usb2: Fix returning wrong error code
  dmaengine: fsl-qdma: Fix a memory leak related to the queue command DMA
  dmaengine: fsl-qdma: Fix a memory leak related to the status queue DMA
  bonding: remove print in bond_verify_device_path
  HID: apple: Add 2021 magic keyboard FN key mapping
  HID: apple: Swap the Fn and Left Control keys on Apple keyboards
  HID: apple: Add support for the 2021 Magic Keyboard
  net: sysfs: Fix /sys/class/net/<iface> path
  af_unix: fix lockdep positive in sk_diag_dump_icons()
  net: ipv4: fix a memleak in ip_setup_cork
  netfilter: nft_ct: sanitize layer 3 and 4 protocol number in custom expectations
  netfilter: nf_log: replace BUG_ON by WARN_ON_ONCE when putting logger
  llc: call sock_orphan() at release time
  ipv6: Ensure natural alignment of const ipv6 loopback and router addresses
  ixgbe: Fix an error handling path in ixgbe_read_iosf_sb_reg_x550()
  ixgbe: Refactor overtemp event handling
  ixgbe: Refactor returning internal error codes
  ixgbe: Remove non-inclusive language
  net: remove unneeded break
  scsi: isci: Fix an error code problem in isci_io_request_build()
  wifi: cfg80211: fix RCU dereference in __cfg80211_bss_update
  perf: Fix the nr_addr_filters fix
  drm/amdgpu: Release 'adev->pm.fw' before return in 'amdgpu_device_need_post()'
  ceph: fix deadlock or deadcode of misusing dget()
  blk-mq: fix IO hang from sbitmap wakeup race
  virtio_net: Fix "‘%d’ directive writing between 1 and 11 bytes into a region of size 10" warnings
  libsubcmd: Fix memory leak in uniq()
  PCI/AER: Decode Requester ID when no error info found
  fs/kernfs/dir: obey S_ISGID
  usb: hub: Replace hardcoded quirk value with BIT() macro
  PCI: switchtec: Fix stdev_release() crash after surprise hot remove
  PCI: Only override AMD USB controller if required
  mfd: ti_am335x_tscadc: Fix TI SoC dependencies
  i3c: master: cdns: Update maximum prescaler value for i2c clock
  um: net: Fix return type of uml_net_start_xmit()
  um: Don't use vfprintf() for os_info()
  um: Fix naming clash between UML and scheduler
  leds: trigger: panic: Don't register panic notifier if creating the trigger failed
  drm/amdgpu: Drop 'fence' check in 'to_amdgpu_amdkfd_fence()'
  drm/amdgpu: Let KFD sync with VM fences
  clk: mmp: pxa168: Fix memory leak in pxa168_clk_init()
  clk: hi3620: Fix memory leak in hi3620_mmc_clk_init()
  drm/msm/dpu: Ratelimit framedone timeout msgs
  media: ddbridge: fix an error code problem in ddb_probe
  IB/ipoib: Fix mcast list locking
  drm/exynos: Call drm_atomic_helper_shutdown() at shutdown/unbind time
  ALSA: hda: Intel: add HDA_ARL PCI ID support
  PCI: add INTEL_HDA_ARL to pci_ids.h
  media: rockchip: rga: fix swizzling for RGB formats
  media: stk1160: Fixed high volume of stk1160_dbg messages
  drm/mipi-dsi: Fix detach call without attach
  drm/framebuffer: Fix use of uninitialized variable
  drm/drm_file: fix use of uninitialized variable
  RDMA/IPoIB: Fix error code return in ipoib_mcast_join
  fast_dput(): handle underflows gracefully
  ASoC: doc: Fix undefined SND_SOC_DAPM_NOPM argument
  f2fs: fix to check return value of f2fs_reserve_new_block()
  wifi: cfg80211: free beacon_ies when overridden from hidden BSS
  wifi: rtlwifi: rtl8723{be,ae}: using calculate_bit_shift()
  wifi: rtl8xxxu: Add additional USB IDs for RTL8192EU devices
  arm64: dts: qcom: msm8998: Fix 'out-ports' is a required property
  arm64: dts: qcom: msm8996: Fix 'in-ports' is a required property
  md: Whenassemble the array, consult the superblock of the freshest device
  block: prevent an integer overflow in bvec_try_merge_hw_page
  ARM: dts: imx23/28: Fix the DMA controller node name
  ARM: dts: imx23-sansa: Use preferred i2c-gpios properties
  ARM: dts: imx27-apf27dev: Fix LED name
  ARM: dts: imx25/27: Pass timing0
  ARM: dts: imx1: Fix sram node
  ARM: dts: imx27: Fix sram node
  ARM: dts: imx: Use flash@0,0 pattern
  ARM: dts: imx25/27-eukrea: Fix RTC node name
  ARM: dts: rockchip: fix rk3036 hdmi ports node
  scsi: libfc: Fix up timeout error in fc_fcp_rec_error()
  scsi: libfc: Don't schedule abort twice
  bpf: Add map and need_defer parameters to .map_fd_put_ptr()
  wifi: ath9k: Fix potential array-index-out-of-bounds read in ath9k_htc_txstatus()
  ARM: dts: imx7s: Fix nand-controller #size-cells
  ARM: dts: imx7s: Fix lcdif compatible
  ARM: dts: imx7d: Fix coresight funnel ports
  bonding: return -ENOMEM instead of BUG in alb_upper_dev_walk
  PCI: Add no PM reset quirk for NVIDIA Spectrum devices
  scsi: lpfc: Fix possible file string name overflow when updating firmware
  selftests/bpf: Fix pyperf180 compilation failure with clang18
  selftests/bpf: satisfy compiler by having explicit return in btf test
  wifi: rt2x00: restart beacon queue when hardware reset
  ext4: avoid online resizing failures due to oversized flex bg
  ext4: remove unnecessary check from alloc_flex_gd()
  ext4: unify the type of flexbg_size to unsigned int
  ext4: fix inconsistent between segment fstrim and full fstrim
  ecryptfs: Reject casefold directory inodes
  SUNRPC: Fix a suspicious RCU usage warning
  KVM: s390: fix setting of fpc register
  s390/ptrace: handle setting of fpc register correctly
  jfs: fix array-index-out-of-bounds in diNewExt
  rxrpc_find_service_conn_rcu: fix the usage of read_seqbegin_or_lock()
  afs: fix the usage of read_seqbegin_or_lock() in afs_find_server*()
  crypto: stm32/crc32 - fix parsing list of devices
  pstore/ram: Fix crash when setting number of cpus to an odd number
  jfs: fix uaf in jfs_evict_inode
  jfs: fix array-index-out-of-bounds in dbAdjTree
  jfs: fix slab-out-of-bounds Read in dtSearch
  UBSAN: array-index-out-of-bounds in dtSplitRoot
  FS:JFS:UBSAN:array-index-out-of-bounds in dbAdjTree
  ACPI: extlog: fix NULL pointer dereference check
  PNP: ACPI: fix fortify warning
  ACPI: video: Add quirk for the Colorful X15 AT 23 Laptop
  audit: Send netlink ACK before setting connection in auditd_set
  regulator: core: Only increment use_count when enable_count changes
  perf/core: Fix narrow startup race when creating the perf nr_addr_filters sysfs file
  x86/mce: Mark fatal MCE's page as poison to avoid panic in the kdump kernel
  powerpc/lib: Validate size for vector operations
  powerpc: pmd_move_must_withdraw() is only needed for CONFIG_TRANSPARENT_HUGEPAGE
  powerpc/mm: Fix build failures due to arch_reserved_kernel_pages()
  powerpc: Fix build error due to is_valid_bugaddr()
  powerpc/mm: Fix null-pointer dereference in pgtable_cache_add
  x86/entry/ia32: Ensure s32 is sign extended to s64
  tick/sched: Preserve number of idle sleeps across CPU hotplug events
  mips: Call lose_fpu(0) before initializing fcr31 in mips_set_personality_nan
  spi: bcm-qspi: fix SFDP BFPT read by usig mspi read
  gpio: eic-sprd: Clear interrupt after set the interrupt type
  drm/exynos: gsc: minor fix for loop iteration in gsc_runtime_resume
  drm/exynos: fix accidental on-stack copy of exynos_drm_plane
  drm/bridge: nxp-ptn3460: simplify some error checking
  drm/bridge: nxp-ptn3460: fix i2c_master_send() error checking
  drm: Don't unref the same fb many times by mistake due to deadlock handling
  gpiolib: acpi: Ignore touchpad wakeup on GPD G1619-04
  netfilter: nf_tables: reject QUEUE/DROP verdict parameters
  rbd: don't move requests to the running list on errors
  btrfs: defrag: reject unknown flags of btrfs_ioctl_defrag_range_args
  btrfs: don't warn if discard range is not aligned to sector
  btrfs: tree-checker: fix inline ref size in error messages
  btrfs: ref-verify: free ref cache before clearing mount opt
  net: fec: fix the unhandled context fault from smmu
  fjes: fix memleaks in fjes_hw_setup
  netfilter: nf_tables: validate NFPROTO_* family
  netfilter: nf_tables: restrict anonymous set and map names to 16 bytes
  net/mlx5e: fix a double-free in arfs_create_groups
  net/mlx5: Use kfree(ft->g) in arfs_create_groups()
  net/mlx5: DR, Use the right GVMI number for drop action
  netlink: fix potential sleeping issue in mqueue_flush_file
  tcp: Add memory barrier to tcp_push()
  afs: Hide silly-rename files from userspace
  tracing: Ensure visibility when inserting an element into tracing_map
  net/rds: Fix UBSAN: array-index-out-of-bounds in rds_cmsg_recv
  llc: Drop support for ETH_P_TR_802_2.
  llc: make llc_ui_sendmsg() more robust against bonding changes
  vlan: skip nested type that is not IFLA_VLAN_QOS_MAPPING
  net/smc: fix illegal rmb_desc access in SMC-D connection dump
  x86/CPU/AMD: Fix disabling XSAVES on AMD family 0x17 due to erratum
  powerpc: Use always instead of always-y in for crtsavres.o
  fs: move S_ISGID stripping into the vfs_*() helpers
  fs: add mode_strip_sgid() helper
  mtd: spinand: macronix: Fix MX35LFxGE4AD page size
  block: Remove special-casing of compound pages
  rename(): fix the locking of subdirectories
  ubifs: ubifs_symlink: Fix memleak of inode->i_link in error path
  nouveau/vmm: don't set addr on the fail path to avoid warning
  mmc: core: Use mrq.sbc in close-ended ffu
  arm64: dts: qcom: sdm845: fix USB wakeup interrupt types
  parisc/firmware: Fix F-extend for PDC addresses
  rpmsg: virtio: Free driver_override when rpmsg_remove()
  hwrng: core - Fix page fault dead lock on mmap-ed hwrng
  PM: hibernate: Enforce ordering during image compression/decompression
  crypto: api - Disallow identical driver names
  ext4: allow for the last group to be marked as trimmed
  serial: sc16is7xx: add check for unsupported SPI modes during probe
  spi: introduce SPI_MODE_X_MASK macro
  serial: sc16is7xx: set safe default SPI clock frequency
  units: add the HZ macros
  units: change from 'L' to 'UL'
  units: Add Watt units
  include/linux/units.h: add helpers for kelvin to/from Celsius conversion
  PCI: mediatek: Clear interrupt status before dispatching handler

 Conflicts:
	include/linux/timer.h
	mm/memory-failure.c

Change-Id: I4974903c79ecddc3d9225b0b723a30b6c83ef572
2024-06-22 17:58:09 +03:00

2402 lines
61 KiB
C

/*
* An async IO implementation for Linux
* Written by Benjamin LaHaise <bcrl@kvack.org>
*
* Implements an efficient asynchronous io interface.
*
* Copyright 2000, 2001, 2002 Red Hat, Inc. All Rights Reserved.
* Copyright 2018 Christoph Hellwig.
*
* See ../COPYING for licensing terms.
*/
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/time.h>
#include <linux/aio_abi.h>
#include <linux/export.h>
#include <linux/syscalls.h>
#include <linux/backing-dev.h>
#include <linux/refcount.h>
#include <linux/uio.h>
#include <linux/sched/signal.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/mmu_context.h>
#include <linux/percpu.h>
#include <linux/slab.h>
#include <linux/timer.h>
#include <linux/aio.h>
#include <linux/highmem.h>
#include <linux/workqueue.h>
#include <linux/security.h>
#include <linux/eventfd.h>
#include <linux/blkdev.h>
#include <linux/compat.h>
#include <linux/migrate.h>
#include <linux/ramfs.h>
#include <linux/percpu-refcount.h>
#include <linux/mount.h>
#include <linux/pseudo_fs.h>
#include <asm/kmap_types.h>
#include <linux/uaccess.h>
#include <linux/nospec.h>
#include "internal.h"
#define KIOCB_KEY 0
#define AIO_RING_MAGIC 0xa10a10a1
#define AIO_RING_COMPAT_FEATURES 1
#define AIO_RING_INCOMPAT_FEATURES 0
struct aio_ring {
unsigned id; /* kernel internal index number */
unsigned nr; /* number of io_events */
unsigned head; /* Written to by userland or under ring_lock
* mutex by aio_read_events_ring(). */
unsigned tail;
unsigned magic;
unsigned compat_features;
unsigned incompat_features;
unsigned header_length; /* size of aio_ring */
struct io_event io_events[0];
}; /* 128 bytes + ring size */
#define AIO_RING_PAGES 8
struct kioctx_table {
struct rcu_head rcu;
unsigned nr;
struct kioctx __rcu *table[];
};
struct kioctx_cpu {
unsigned reqs_available;
};
struct ctx_rq_wait {
struct completion comp;
atomic_t count;
};
struct kioctx {
struct percpu_ref users;
atomic_t dead;
struct percpu_ref reqs;
unsigned long user_id;
struct __percpu kioctx_cpu *cpu;
/*
* For percpu reqs_available, number of slots we move to/from global
* counter at a time:
*/
unsigned req_batch;
/*
* This is what userspace passed to io_setup(), it's not used for
* anything but counting against the global max_reqs quota.
*
* The real limit is nr_events - 1, which will be larger (see
* aio_setup_ring())
*/
unsigned max_reqs;
/* Size of ringbuffer, in units of struct io_event */
unsigned nr_events;
unsigned long mmap_base;
unsigned long mmap_size;
struct page **ring_pages;
long nr_pages;
struct rcu_work free_rwork; /* see free_ioctx() */
/*
* signals when all in-flight requests are done
*/
struct ctx_rq_wait *rq_wait;
struct {
/*
* This counts the number of available slots in the ringbuffer,
* so we avoid overflowing it: it's decremented (if positive)
* when allocating a kiocb and incremented when the resulting
* io_event is pulled off the ringbuffer.
*
* We batch accesses to it with a percpu version.
*/
atomic_t reqs_available;
} ____cacheline_aligned_in_smp;
struct {
spinlock_t ctx_lock;
struct list_head active_reqs; /* used for cancellation */
} ____cacheline_aligned_in_smp;
struct {
struct mutex ring_lock;
wait_queue_head_t wait;
} ____cacheline_aligned_in_smp;
struct {
unsigned tail;
unsigned completed_events;
spinlock_t completion_lock;
} ____cacheline_aligned_in_smp;
struct page *internal_pages[AIO_RING_PAGES];
struct file *aio_ring_file;
unsigned id;
};
/*
* First field must be the file pointer in all the
* iocb unions! See also 'struct kiocb' in <linux/fs.h>
*/
struct fsync_iocb {
struct file *file;
struct work_struct work;
bool datasync;
struct cred *creds;
};
struct poll_iocb {
struct file *file;
struct wait_queue_head *head;
__poll_t events;
bool cancelled;
bool work_scheduled;
bool work_need_resched;
struct wait_queue_entry wait;
struct work_struct work;
};
/*
* NOTE! Each of the iocb union members has the file pointer
* as the first entry in their struct definition. So you can
* access the file pointer through any of the sub-structs,
* or directly as just 'ki_filp' in this struct.
*/
struct aio_kiocb {
union {
struct file *ki_filp;
struct kiocb rw;
struct fsync_iocb fsync;
struct poll_iocb poll;
};
struct kioctx *ki_ctx;
kiocb_cancel_fn *ki_cancel;
struct io_event ki_res;
struct list_head ki_list; /* the aio core uses this
* for cancellation */
refcount_t ki_refcnt;
/*
* If the aio_resfd field of the userspace iocb is not zero,
* this is the underlying eventfd context to deliver events to.
*/
struct eventfd_ctx *ki_eventfd;
};
/*------ sysctl variables----*/
static DEFINE_SPINLOCK(aio_nr_lock);
unsigned long aio_nr; /* current system wide number of aio requests */
unsigned long aio_max_nr = 0x10000; /* system wide maximum number of aio requests */
/*----end sysctl variables---*/
static struct kmem_cache *kiocb_cachep;
static struct kmem_cache *kioctx_cachep;
static struct vfsmount *aio_mnt;
static const struct file_operations aio_ring_fops;
static const struct address_space_operations aio_ctx_aops;
static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages)
{
struct file *file;
struct inode *inode = alloc_anon_inode(aio_mnt->mnt_sb);
if (IS_ERR(inode))
return ERR_CAST(inode);
inode->i_mapping->a_ops = &aio_ctx_aops;
inode->i_mapping->private_data = ctx;
inode->i_size = PAGE_SIZE * nr_pages;
file = alloc_file_pseudo(inode, aio_mnt, "[aio]",
O_RDWR, &aio_ring_fops);
if (IS_ERR(file))
iput(inode);
return file;
}
static int aio_init_fs_context(struct fs_context *fc)
{
if (!init_pseudo(fc, AIO_RING_MAGIC))
return -ENOMEM;
fc->s_iflags |= SB_I_NOEXEC;
return 0;
}
/* aio_setup
* Creates the slab caches used by the aio routines, panic on
* failure as this is done early during the boot sequence.
*/
static int __init aio_setup(void)
{
static struct file_system_type aio_fs = {
.name = "aio",
.init_fs_context = aio_init_fs_context,
.kill_sb = kill_anon_super,
};
aio_mnt = kern_mount(&aio_fs);
if (IS_ERR(aio_mnt))
panic("Failed to create aio fs mount.");
kiocb_cachep = KMEM_CACHE(aio_kiocb, SLAB_HWCACHE_ALIGN|SLAB_PANIC);
kioctx_cachep = KMEM_CACHE(kioctx,SLAB_HWCACHE_ALIGN|SLAB_PANIC);
return 0;
}
__initcall(aio_setup);
static void put_aio_ring_file(struct kioctx *ctx)
{
struct file *aio_ring_file = ctx->aio_ring_file;
struct address_space *i_mapping;
if (aio_ring_file) {
truncate_setsize(file_inode(aio_ring_file), 0);
/* Prevent further access to the kioctx from migratepages */
i_mapping = aio_ring_file->f_mapping;
spin_lock(&i_mapping->private_lock);
i_mapping->private_data = NULL;
ctx->aio_ring_file = NULL;
spin_unlock(&i_mapping->private_lock);
fput(aio_ring_file);
}
}
static void aio_free_ring(struct kioctx *ctx)
{
int i;
/* Disconnect the kiotx from the ring file. This prevents future
* accesses to the kioctx from page migration.
*/
put_aio_ring_file(ctx);
for (i = 0; i < ctx->nr_pages; i++) {
struct page *page;
pr_debug("pid(%d) [%d] page->count=%d\n", current->pid, i,
page_count(ctx->ring_pages[i]));
page = ctx->ring_pages[i];
if (!page)
continue;
ctx->ring_pages[i] = NULL;
put_page(page);
}
if (ctx->ring_pages && ctx->ring_pages != ctx->internal_pages) {
kfree(ctx->ring_pages);
ctx->ring_pages = NULL;
}
}
static int aio_ring_mremap(struct vm_area_struct *vma)
{
struct file *file = vma->vm_file;
struct mm_struct *mm = vma->vm_mm;
struct kioctx_table *table;
int i, res = -EINVAL;
spin_lock(&mm->ioctx_lock);
rcu_read_lock();
table = rcu_dereference(mm->ioctx_table);
if (!table)
goto out_unlock;
for (i = 0; i < table->nr; i++) {
struct kioctx *ctx;
ctx = rcu_dereference(table->table[i]);
if (ctx && ctx->aio_ring_file == file) {
if (!atomic_read(&ctx->dead)) {
ctx->user_id = ctx->mmap_base = vma->vm_start;
res = 0;
}
break;
}
}
out_unlock:
rcu_read_unlock();
spin_unlock(&mm->ioctx_lock);
return res;
}
static const struct vm_operations_struct aio_ring_vm_ops = {
.mremap = aio_ring_mremap,
#if IS_ENABLED(CONFIG_MMU)
.fault = filemap_fault,
.map_pages = filemap_map_pages,
.page_mkwrite = filemap_page_mkwrite,
#endif
};
static int aio_ring_mmap(struct file *file, struct vm_area_struct *vma)
{
vma->vm_flags |= VM_DONTEXPAND;
vma->vm_ops = &aio_ring_vm_ops;
return 0;
}
static const struct file_operations aio_ring_fops = {
.mmap = aio_ring_mmap,
};
#if IS_ENABLED(CONFIG_MIGRATION)
static int aio_migratepage(struct address_space *mapping, struct page *new,
struct page *old, enum migrate_mode mode)
{
struct kioctx *ctx;
unsigned long flags;
pgoff_t idx;
int rc;
/*
* We cannot support the _NO_COPY case here, because copy needs to
* happen under the ctx->completion_lock. That does not work with the
* migration workflow of MIGRATE_SYNC_NO_COPY.
*/
if (mode == MIGRATE_SYNC_NO_COPY)
return -EINVAL;
rc = 0;
/* mapping->private_lock here protects against the kioctx teardown. */
spin_lock(&mapping->private_lock);
ctx = mapping->private_data;
if (!ctx) {
rc = -EINVAL;
goto out;
}
/* The ring_lock mutex. The prevents aio_read_events() from writing
* to the ring's head, and prevents page migration from mucking in
* a partially initialized kiotx.
*/
if (!mutex_trylock(&ctx->ring_lock)) {
rc = -EAGAIN;
goto out;
}
idx = old->index;
if (idx < (pgoff_t)ctx->nr_pages) {
/* Make sure the old page hasn't already been changed */
if (ctx->ring_pages[idx] != old)
rc = -EAGAIN;
} else
rc = -EINVAL;
if (rc != 0)
goto out_unlock;
/* Writeback must be complete */
BUG_ON(PageWriteback(old));
get_page(new);
rc = migrate_page_move_mapping(mapping, new, old, 1);
if (rc != MIGRATEPAGE_SUCCESS) {
put_page(new);
goto out_unlock;
}
/* Take completion_lock to prevent other writes to the ring buffer
* while the old page is copied to the new. This prevents new
* events from being lost.
*/
spin_lock_irqsave(&ctx->completion_lock, flags);
migrate_page_copy(new, old);
BUG_ON(ctx->ring_pages[idx] != old);
ctx->ring_pages[idx] = new;
spin_unlock_irqrestore(&ctx->completion_lock, flags);
/* The old page is no longer accessible. */
put_page(old);
out_unlock:
mutex_unlock(&ctx->ring_lock);
out:
spin_unlock(&mapping->private_lock);
return rc;
}
#endif
static const struct address_space_operations aio_ctx_aops = {
.set_page_dirty = __set_page_dirty_no_writeback,
#if IS_ENABLED(CONFIG_MIGRATION)
.migratepage = aio_migratepage,
#endif
};
static int aio_setup_ring(struct kioctx *ctx, unsigned int nr_events)
{
struct aio_ring *ring;
struct mm_struct *mm = current->mm;
unsigned long size, unused;
int nr_pages;
int i;
struct file *file;
/* Compensate for the ring buffer's head/tail overlap entry */
nr_events += 2; /* 1 is required, 2 for good luck */
size = sizeof(struct aio_ring);
size += sizeof(struct io_event) * nr_events;
nr_pages = PFN_UP(size);
if (nr_pages < 0)
return -EINVAL;
file = aio_private_file(ctx, nr_pages);
if (IS_ERR(file)) {
ctx->aio_ring_file = NULL;
return -ENOMEM;
}
ctx->aio_ring_file = file;
nr_events = (PAGE_SIZE * nr_pages - sizeof(struct aio_ring))
/ sizeof(struct io_event);
ctx->ring_pages = ctx->internal_pages;
if (nr_pages > AIO_RING_PAGES) {
ctx->ring_pages = kcalloc(nr_pages, sizeof(struct page *),
GFP_KERNEL);
if (!ctx->ring_pages) {
put_aio_ring_file(ctx);
return -ENOMEM;
}
}
for (i = 0; i < nr_pages; i++) {
struct page *page;
page = find_or_create_page(file->f_mapping,
i, GFP_HIGHUSER | __GFP_ZERO);
if (!page)
break;
pr_debug("pid(%d) page[%d]->count=%d\n",
current->pid, i, page_count(page));
SetPageUptodate(page);
unlock_page(page);
ctx->ring_pages[i] = page;
}
ctx->nr_pages = i;
if (unlikely(i != nr_pages)) {
aio_free_ring(ctx);
return -ENOMEM;
}
ctx->mmap_size = nr_pages * PAGE_SIZE;
pr_debug("attempting mmap of %lu bytes\n", ctx->mmap_size);
if (down_write_killable(&mm->mmap_sem)) {
ctx->mmap_size = 0;
aio_free_ring(ctx);
return -EINTR;
}
ctx->mmap_base = do_mmap_pgoff(ctx->aio_ring_file, 0, ctx->mmap_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, 0, &unused, NULL);
up_write(&mm->mmap_sem);
if (IS_ERR((void *)ctx->mmap_base)) {
ctx->mmap_size = 0;
aio_free_ring(ctx);
return -ENOMEM;
}
pr_debug("mmap address: 0x%08lx\n", ctx->mmap_base);
ctx->user_id = ctx->mmap_base;
ctx->nr_events = nr_events; /* trusted copy */
ring = kmap_atomic(ctx->ring_pages[0]);
ring->nr = nr_events; /* user copy */
ring->id = ~0U;
ring->head = ring->tail = 0;
ring->magic = AIO_RING_MAGIC;
ring->compat_features = AIO_RING_COMPAT_FEATURES;
ring->incompat_features = AIO_RING_INCOMPAT_FEATURES;
ring->header_length = sizeof(struct aio_ring);
kunmap_atomic(ring);
flush_dcache_page(ctx->ring_pages[0]);
return 0;
}
#define AIO_EVENTS_PER_PAGE (PAGE_SIZE / sizeof(struct io_event))
#define AIO_EVENTS_FIRST_PAGE ((PAGE_SIZE - sizeof(struct aio_ring)) / sizeof(struct io_event))
#define AIO_EVENTS_OFFSET (AIO_EVENTS_PER_PAGE - AIO_EVENTS_FIRST_PAGE)
void kiocb_set_cancel_fn(struct kiocb *iocb, kiocb_cancel_fn *cancel)
{
struct aio_kiocb *req;
struct kioctx *ctx;
unsigned long flags;
/*
* kiocb didn't come from aio or is neither a read nor a write, hence
* ignore it.
*/
if (!(iocb->ki_flags & IOCB_AIO_RW))
return;
req = container_of(iocb, struct aio_kiocb, rw);
if (WARN_ON_ONCE(!list_empty(&req->ki_list)))
return;
ctx = req->ki_ctx;
spin_lock_irqsave(&ctx->ctx_lock, flags);
list_add_tail(&req->ki_list, &ctx->active_reqs);
req->ki_cancel = cancel;
spin_unlock_irqrestore(&ctx->ctx_lock, flags);
}
EXPORT_SYMBOL(kiocb_set_cancel_fn);
/*
* free_ioctx() should be RCU delayed to synchronize against the RCU
* protected lookup_ioctx() and also needs process context to call
* aio_free_ring(). Use rcu_work.
*/
static void free_ioctx(struct work_struct *work)
{
struct kioctx *ctx = container_of(to_rcu_work(work), struct kioctx,
free_rwork);
pr_debug("freeing %p\n", ctx);
aio_free_ring(ctx);
free_percpu(ctx->cpu);
percpu_ref_exit(&ctx->reqs);
percpu_ref_exit(&ctx->users);
kmem_cache_free(kioctx_cachep, ctx);
}
static void free_ioctx_reqs(struct percpu_ref *ref)
{
struct kioctx *ctx = container_of(ref, struct kioctx, reqs);
/* At this point we know that there are no any in-flight requests */
if (ctx->rq_wait && atomic_dec_and_test(&ctx->rq_wait->count))
complete(&ctx->rq_wait->comp);
/* Synchronize against RCU protected table->table[] dereferences */
INIT_RCU_WORK(&ctx->free_rwork, free_ioctx);
queue_rcu_work(system_wq, &ctx->free_rwork);
}
/*
* When this function runs, the kioctx has been removed from the "hash table"
* and ctx->users has dropped to 0, so we know no more kiocbs can be submitted -
* now it's safe to cancel any that need to be.
*/
static void free_ioctx_users(struct percpu_ref *ref)
{
struct kioctx *ctx = container_of(ref, struct kioctx, users);
struct aio_kiocb *req;
spin_lock_irq(&ctx->ctx_lock);
while (!list_empty(&ctx->active_reqs)) {
req = list_first_entry(&ctx->active_reqs,
struct aio_kiocb, ki_list);
req->ki_cancel(&req->rw);
list_del_init(&req->ki_list);
}
spin_unlock_irq(&ctx->ctx_lock);
percpu_ref_kill(&ctx->reqs);
percpu_ref_put(&ctx->reqs);
}
static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm)
{
unsigned i, new_nr;
struct kioctx_table *table, *old;
struct aio_ring *ring;
spin_lock(&mm->ioctx_lock);
table = rcu_dereference_raw(mm->ioctx_table);
while (1) {
if (table)
for (i = 0; i < table->nr; i++)
if (!rcu_access_pointer(table->table[i])) {
ctx->id = i;
rcu_assign_pointer(table->table[i], ctx);
spin_unlock(&mm->ioctx_lock);
/* While kioctx setup is in progress,
* we are protected from page migration
* changes ring_pages by ->ring_lock.
*/
ring = kmap_atomic(ctx->ring_pages[0]);
ring->id = ctx->id;
kunmap_atomic(ring);
return 0;
}
new_nr = (table ? table->nr : 1) * 4;
spin_unlock(&mm->ioctx_lock);
table = kzalloc(sizeof(*table) + sizeof(struct kioctx *) *
new_nr, GFP_KERNEL);
if (!table)
return -ENOMEM;
table->nr = new_nr;
spin_lock(&mm->ioctx_lock);
old = rcu_dereference_raw(mm->ioctx_table);
if (!old) {
rcu_assign_pointer(mm->ioctx_table, table);
} else if (table->nr > old->nr) {
memcpy(table->table, old->table,
old->nr * sizeof(struct kioctx *));
rcu_assign_pointer(mm->ioctx_table, table);
kfree_rcu(old, rcu);
} else {
kfree(table);
table = old;
}
}
}
static void aio_nr_sub(unsigned nr)
{
spin_lock(&aio_nr_lock);
if (WARN_ON(aio_nr - nr > aio_nr))
aio_nr = 0;
else
aio_nr -= nr;
spin_unlock(&aio_nr_lock);
}
/* ioctx_alloc
* Allocates and initializes an ioctx. Returns an ERR_PTR if it failed.
*/
static struct kioctx *ioctx_alloc(unsigned nr_events)
{
struct mm_struct *mm = current->mm;
struct kioctx *ctx;
int err = -ENOMEM;
/*
* Store the original nr_events -- what userspace passed to io_setup(),
* for counting against the global limit -- before it changes.
*/
unsigned int max_reqs = nr_events;
/*
* We keep track of the number of available ringbuffer slots, to prevent
* overflow (reqs_available), and we also use percpu counters for this.
*
* So since up to half the slots might be on other cpu's percpu counters
* and unavailable, double nr_events so userspace sees what they
* expected: additionally, we move req_batch slots to/from percpu
* counters at a time, so make sure that isn't 0:
*/
nr_events = max(nr_events, num_possible_cpus() * 4);
nr_events *= 2;
/* Prevent overflows */
if (nr_events > (0x10000000U / sizeof(struct io_event))) {
pr_debug("ENOMEM: nr_events too high\n");
return ERR_PTR(-EINVAL);
}
if (!nr_events || (unsigned long)max_reqs > aio_max_nr)
return ERR_PTR(-EAGAIN);
ctx = kmem_cache_zalloc(kioctx_cachep, GFP_KERNEL);
if (!ctx)
return ERR_PTR(-ENOMEM);
ctx->max_reqs = max_reqs;
spin_lock_init(&ctx->ctx_lock);
spin_lock_init(&ctx->completion_lock);
mutex_init(&ctx->ring_lock);
/* Protect against page migration throughout kiotx setup by keeping
* the ring_lock mutex held until setup is complete. */
mutex_lock(&ctx->ring_lock);
init_waitqueue_head(&ctx->wait);
INIT_LIST_HEAD(&ctx->active_reqs);
if (percpu_ref_init(&ctx->users, free_ioctx_users, 0, GFP_KERNEL))
goto err;
if (percpu_ref_init(&ctx->reqs, free_ioctx_reqs, 0, GFP_KERNEL))
goto err;
ctx->cpu = alloc_percpu(struct kioctx_cpu);
if (!ctx->cpu)
goto err;
err = aio_setup_ring(ctx, nr_events);
if (err < 0)
goto err;
atomic_set(&ctx->reqs_available, ctx->nr_events - 1);
ctx->req_batch = (ctx->nr_events - 1) / (num_possible_cpus() * 4);
if (ctx->req_batch < 1)
ctx->req_batch = 1;
/* limit the number of system wide aios */
spin_lock(&aio_nr_lock);
if (aio_nr + ctx->max_reqs > aio_max_nr ||
aio_nr + ctx->max_reqs < aio_nr) {
spin_unlock(&aio_nr_lock);
err = -EAGAIN;
goto err_ctx;
}
aio_nr += ctx->max_reqs;
spin_unlock(&aio_nr_lock);
percpu_ref_get(&ctx->users); /* io_setup() will drop this ref */
percpu_ref_get(&ctx->reqs); /* free_ioctx_users() will drop this */
err = ioctx_add_table(ctx, mm);
if (err)
goto err_cleanup;
/* Release the ring_lock mutex now that all setup is complete. */
mutex_unlock(&ctx->ring_lock);
pr_debug("allocated ioctx %p[%ld]: mm=%p mask=0x%x\n",
ctx, ctx->user_id, mm, ctx->nr_events);
return ctx;
err_cleanup:
aio_nr_sub(ctx->max_reqs);
err_ctx:
atomic_set(&ctx->dead, 1);
if (ctx->mmap_size)
vm_munmap(ctx->mmap_base, ctx->mmap_size);
aio_free_ring(ctx);
err:
mutex_unlock(&ctx->ring_lock);
free_percpu(ctx->cpu);
percpu_ref_exit(&ctx->reqs);
percpu_ref_exit(&ctx->users);
kmem_cache_free(kioctx_cachep, ctx);
pr_debug("error allocating ioctx %d\n", err);
return ERR_PTR(err);
}
/* kill_ioctx
* Cancels all outstanding aio requests on an aio context. Used
* when the processes owning a context have all exited to encourage
* the rapid destruction of the kioctx.
*/
static int kill_ioctx(struct mm_struct *mm, struct kioctx *ctx,
struct ctx_rq_wait *wait)
{
struct kioctx_table *table;
spin_lock(&mm->ioctx_lock);
if (atomic_xchg(&ctx->dead, 1)) {
spin_unlock(&mm->ioctx_lock);
return -EINVAL;
}
table = rcu_dereference_raw(mm->ioctx_table);
WARN_ON(ctx != rcu_access_pointer(table->table[ctx->id]));
RCU_INIT_POINTER(table->table[ctx->id], NULL);
spin_unlock(&mm->ioctx_lock);
/* free_ioctx_reqs() will do the necessary RCU synchronization */
wake_up_all(&ctx->wait);
/*
* It'd be more correct to do this in free_ioctx(), after all
* the outstanding kiocbs have finished - but by then io_destroy
* has already returned, so io_setup() could potentially return
* -EAGAIN with no ioctxs actually in use (as far as userspace
* could tell).
*/
aio_nr_sub(ctx->max_reqs);
if (ctx->mmap_size)
vm_munmap(ctx->mmap_base, ctx->mmap_size);
ctx->rq_wait = wait;
percpu_ref_kill(&ctx->users);
return 0;
}
/*
* exit_aio: called when the last user of mm goes away. At this point, there is
* no way for any new requests to be submited or any of the io_* syscalls to be
* called on the context.
*
* There may be outstanding kiocbs, but free_ioctx() will explicitly wait on
* them.
*/
void exit_aio(struct mm_struct *mm)
{
struct kioctx_table *table = rcu_dereference_raw(mm->ioctx_table);
struct ctx_rq_wait wait;
int i, skipped;
if (!table)
return;
atomic_set(&wait.count, table->nr);
init_completion(&wait.comp);
skipped = 0;
for (i = 0; i < table->nr; ++i) {
struct kioctx *ctx =
rcu_dereference_protected(table->table[i], true);
if (!ctx) {
skipped++;
continue;
}
/*
* We don't need to bother with munmap() here - exit_mmap(mm)
* is coming and it'll unmap everything. And we simply can't,
* this is not necessarily our ->mm.
* Since kill_ioctx() uses non-zero ->mmap_size as indicator
* that it needs to unmap the area, just set it to 0.
*/
ctx->mmap_size = 0;
kill_ioctx(mm, ctx, &wait);
}
if (!atomic_sub_and_test(skipped, &wait.count)) {
/* Wait until all IO for the context are done. */
wait_for_completion(&wait.comp);
}
RCU_INIT_POINTER(mm->ioctx_table, NULL);
kfree(table);
}
static void put_reqs_available(struct kioctx *ctx, unsigned nr)
{
struct kioctx_cpu *kcpu;
unsigned long flags;
local_irq_save(flags);
kcpu = this_cpu_ptr(ctx->cpu);
kcpu->reqs_available += nr;
while (kcpu->reqs_available >= ctx->req_batch * 2) {
kcpu->reqs_available -= ctx->req_batch;
atomic_add(ctx->req_batch, &ctx->reqs_available);
}
local_irq_restore(flags);
}
static bool __get_reqs_available(struct kioctx *ctx)
{
struct kioctx_cpu *kcpu;
bool ret = false;
unsigned long flags;
local_irq_save(flags);
kcpu = this_cpu_ptr(ctx->cpu);
if (!kcpu->reqs_available) {
int old, avail = atomic_read(&ctx->reqs_available);
do {
if (avail < ctx->req_batch)
goto out;
old = avail;
avail = atomic_cmpxchg(&ctx->reqs_available,
avail, avail - ctx->req_batch);
} while (avail != old);
kcpu->reqs_available += ctx->req_batch;
}
ret = true;
kcpu->reqs_available--;
out:
local_irq_restore(flags);
return ret;
}
/* refill_reqs_available
* Updates the reqs_available reference counts used for tracking the
* number of free slots in the completion ring. This can be called
* from aio_complete() (to optimistically update reqs_available) or
* from aio_get_req() (the we're out of events case). It must be
* called holding ctx->completion_lock.
*/
static void refill_reqs_available(struct kioctx *ctx, unsigned head,
unsigned tail)
{
unsigned events_in_ring, completed;
/* Clamp head since userland can write to it. */
head %= ctx->nr_events;
if (head <= tail)
events_in_ring = tail - head;
else
events_in_ring = ctx->nr_events - (head - tail);
completed = ctx->completed_events;
if (events_in_ring < completed)
completed -= events_in_ring;
else
completed = 0;
if (!completed)
return;
ctx->completed_events -= completed;
put_reqs_available(ctx, completed);
}
/* user_refill_reqs_available
* Called to refill reqs_available when aio_get_req() encounters an
* out of space in the completion ring.
*/
static void user_refill_reqs_available(struct kioctx *ctx)
{
spin_lock_irq(&ctx->completion_lock);
if (ctx->completed_events) {
struct aio_ring *ring;
unsigned head;
/* Access of ring->head may race with aio_read_events_ring()
* here, but that's okay since whether we read the old version
* or the new version, and either will be valid. The important
* part is that head cannot pass tail since we prevent
* aio_complete() from updating tail by holding
* ctx->completion_lock. Even if head is invalid, the check
* against ctx->completed_events below will make sure we do the
* safe/right thing.
*/
ring = kmap_atomic(ctx->ring_pages[0]);
head = ring->head;
kunmap_atomic(ring);
refill_reqs_available(ctx, head, ctx->tail);
}
spin_unlock_irq(&ctx->completion_lock);
}
static bool get_reqs_available(struct kioctx *ctx)
{
if (__get_reqs_available(ctx))
return true;
user_refill_reqs_available(ctx);
return __get_reqs_available(ctx);
}
/* aio_get_req
* Allocate a slot for an aio request.
* Returns NULL if no requests are free.
*
* The refcount is initialized to 2 - one for the async op completion,
* one for the synchronous code that does this.
*/
static inline struct aio_kiocb *aio_get_req(struct kioctx *ctx)
{
struct aio_kiocb *req;
req = kmem_cache_alloc(kiocb_cachep, GFP_KERNEL);
if (unlikely(!req))
return NULL;
if (unlikely(!get_reqs_available(ctx))) {
kmem_cache_free(kiocb_cachep, req);
return NULL;
}
percpu_ref_get(&ctx->reqs);
req->ki_ctx = ctx;
INIT_LIST_HEAD(&req->ki_list);
refcount_set(&req->ki_refcnt, 2);
req->ki_eventfd = NULL;
return req;
}
static struct kioctx *lookup_ioctx(unsigned long ctx_id)
{
struct aio_ring __user *ring = (void __user *)ctx_id;
struct mm_struct *mm = current->mm;
struct kioctx *ctx, *ret = NULL;
struct kioctx_table *table;
unsigned id;
if (get_user(id, &ring->id))
return NULL;
rcu_read_lock();
table = rcu_dereference(mm->ioctx_table);
if (!table || id >= table->nr)
goto out;
id = array_index_nospec(id, table->nr);
ctx = rcu_dereference(table->table[id]);
if (ctx && ctx->user_id == ctx_id) {
if (percpu_ref_tryget_live(&ctx->users))
ret = ctx;
}
out:
rcu_read_unlock();
return ret;
}
static inline void iocb_destroy(struct aio_kiocb *iocb)
{
if (iocb->ki_eventfd)
eventfd_ctx_put(iocb->ki_eventfd);
if (iocb->ki_filp)
fput(iocb->ki_filp);
percpu_ref_put(&iocb->ki_ctx->reqs);
kmem_cache_free(kiocb_cachep, iocb);
}
/* aio_complete
* Called when the io request on the given iocb is complete.
*/
static void aio_complete(struct aio_kiocb *iocb)
{
struct kioctx *ctx = iocb->ki_ctx;
struct aio_ring *ring;
struct io_event *ev_page, *event;
unsigned tail, pos, head;
unsigned long flags;
/*
* Add a completion event to the ring buffer. Must be done holding
* ctx->completion_lock to prevent other code from messing with the tail
* pointer since we might be called from irq context.
*/
spin_lock_irqsave(&ctx->completion_lock, flags);
tail = ctx->tail;
pos = tail + AIO_EVENTS_OFFSET;
if (++tail >= ctx->nr_events)
tail = 0;
ev_page = kmap_atomic(ctx->ring_pages[pos / AIO_EVENTS_PER_PAGE]);
event = ev_page + pos % AIO_EVENTS_PER_PAGE;
*event = iocb->ki_res;
kunmap_atomic(ev_page);
flush_dcache_page(ctx->ring_pages[pos / AIO_EVENTS_PER_PAGE]);
pr_debug("%p[%u]: %p: %p %Lx %Lx %Lx\n", ctx, tail, iocb,
(void __user *)(unsigned long)iocb->ki_res.obj,
iocb->ki_res.data, iocb->ki_res.res, iocb->ki_res.res2);
/* after flagging the request as done, we
* must never even look at it again
*/
smp_wmb(); /* make event visible before updating tail */
ctx->tail = tail;
ring = kmap_atomic(ctx->ring_pages[0]);
head = ring->head;
ring->tail = tail;
kunmap_atomic(ring);
flush_dcache_page(ctx->ring_pages[0]);
ctx->completed_events++;
if (ctx->completed_events > 1)
refill_reqs_available(ctx, head, tail);
spin_unlock_irqrestore(&ctx->completion_lock, flags);
pr_debug("added to ring %p at [%u]\n", iocb, tail);
/*
* Check if the user asked us to deliver the result through an
* eventfd. The eventfd_signal() function is safe to be called
* from IRQ context.
*/
if (iocb->ki_eventfd)
eventfd_signal(iocb->ki_eventfd, 1);
/*
* We have to order our ring_info tail store above and test
* of the wait list below outside the wait lock. This is
* like in wake_up_bit() where clearing a bit has to be
* ordered with the unlocked test.
*/
smp_mb();
if (waitqueue_active(&ctx->wait))
wake_up(&ctx->wait);
}
static inline void iocb_put(struct aio_kiocb *iocb)
{
if (refcount_dec_and_test(&iocb->ki_refcnt)) {
aio_complete(iocb);
iocb_destroy(iocb);
}
}
/* aio_read_events_ring
* Pull an event off of the ioctx's event ring. Returns the number of
* events fetched
*/
static long aio_read_events_ring(struct kioctx *ctx,
struct io_event __user *event, long nr)
{
struct aio_ring *ring;
unsigned head, tail, pos;
long ret = 0;
int copy_ret;
/*
* The mutex can block and wake us up and that will cause
* wait_event_interruptible_hrtimeout() to schedule without sleeping
* and repeat. This should be rare enough that it doesn't cause
* peformance issues. See the comment in read_events() for more detail.
*/
sched_annotate_sleep();
mutex_lock(&ctx->ring_lock);
/* Access to ->ring_pages here is protected by ctx->ring_lock. */
ring = kmap_atomic(ctx->ring_pages[0]);
head = ring->head;
tail = ring->tail;
kunmap_atomic(ring);
/*
* Ensure that once we've read the current tail pointer, that
* we also see the events that were stored up to the tail.
*/
smp_rmb();
pr_debug("h%u t%u m%u\n", head, tail, ctx->nr_events);
if (head == tail)
goto out;
head %= ctx->nr_events;
tail %= ctx->nr_events;
while (ret < nr) {
long avail;
struct io_event *ev;
struct page *page;
avail = (head <= tail ? tail : ctx->nr_events) - head;
if (head == tail)
break;
pos = head + AIO_EVENTS_OFFSET;
page = ctx->ring_pages[pos / AIO_EVENTS_PER_PAGE];
pos %= AIO_EVENTS_PER_PAGE;
avail = min(avail, nr - ret);
avail = min_t(long, avail, AIO_EVENTS_PER_PAGE - pos);
ev = kmap(page);
copy_ret = copy_to_user(event + ret, ev + pos,
sizeof(*ev) * avail);
kunmap(page);
if (unlikely(copy_ret)) {
ret = -EFAULT;
goto out;
}
ret += avail;
head += avail;
head %= ctx->nr_events;
}
ring = kmap_atomic(ctx->ring_pages[0]);
ring->head = head;
kunmap_atomic(ring);
flush_dcache_page(ctx->ring_pages[0]);
pr_debug("%li h%u t%u\n", ret, head, tail);
out:
mutex_unlock(&ctx->ring_lock);
return ret;
}
static bool aio_read_events(struct kioctx *ctx, long min_nr, long nr,
struct io_event __user *event, long *i)
{
long ret = aio_read_events_ring(ctx, event + *i, nr - *i);
if (ret > 0)
*i += ret;
if (unlikely(atomic_read(&ctx->dead)))
ret = -EINVAL;
if (!*i)
*i = ret;
return ret < 0 || *i >= min_nr;
}
static long read_events(struct kioctx *ctx, long min_nr, long nr,
struct io_event __user *event,
ktime_t until)
{
long ret = 0;
/*
* Note that aio_read_events() is being called as the conditional - i.e.
* we're calling it after prepare_to_wait() has set task state to
* TASK_INTERRUPTIBLE.
*
* But aio_read_events() can block, and if it blocks it's going to flip
* the task state back to TASK_RUNNING.
*
* This should be ok, provided it doesn't flip the state back to
* TASK_RUNNING and return 0 too much - that causes us to spin. That
* will only happen if the mutex_lock() call blocks, and we then find
* the ringbuffer empty. So in practice we should be ok, but it's
* something to be aware of when touching this code.
*/
if (until == 0)
aio_read_events(ctx, min_nr, nr, event, &ret);
else
wait_event_interruptible_hrtimeout(ctx->wait,
aio_read_events(ctx, min_nr, nr, event, &ret),
until);
return ret;
}
/* sys_io_setup:
* Create an aio_context capable of receiving at least nr_events.
* ctxp must not point to an aio_context that already exists, and
* must be initialized to 0 prior to the call. On successful
* creation of the aio_context, *ctxp is filled in with the resulting
* handle. May fail with -EINVAL if *ctxp is not initialized,
* if the specified nr_events exceeds internal limits. May fail
* with -EAGAIN if the specified nr_events exceeds the user's limit
* of available events. May fail with -ENOMEM if insufficient kernel
* resources are available. May fail with -EFAULT if an invalid
* pointer is passed for ctxp. Will fail with -ENOSYS if not
* implemented.
*/
SYSCALL_DEFINE2(io_setup, unsigned, nr_events, aio_context_t __user *, ctxp)
{
struct kioctx *ioctx = NULL;
unsigned long ctx;
long ret;
ret = get_user(ctx, ctxp);
if (unlikely(ret))
goto out;
ret = -EINVAL;
if (unlikely(ctx || nr_events == 0)) {
pr_debug("EINVAL: ctx %lu nr_events %u\n",
ctx, nr_events);
goto out;
}
ioctx = ioctx_alloc(nr_events);
ret = PTR_ERR(ioctx);
if (!IS_ERR(ioctx)) {
ret = put_user(ioctx->user_id, ctxp);
if (ret)
kill_ioctx(current->mm, ioctx, NULL);
percpu_ref_put(&ioctx->users);
}
out:
return ret;
}
#ifdef CONFIG_COMPAT
COMPAT_SYSCALL_DEFINE2(io_setup, unsigned, nr_events, u32 __user *, ctx32p)
{
struct kioctx *ioctx = NULL;
unsigned long ctx;
long ret;
ret = get_user(ctx, ctx32p);
if (unlikely(ret))
goto out;
ret = -EINVAL;
if (unlikely(ctx || nr_events == 0)) {
pr_debug("EINVAL: ctx %lu nr_events %u\n",
ctx, nr_events);
goto out;
}
ioctx = ioctx_alloc(nr_events);
ret = PTR_ERR(ioctx);
if (!IS_ERR(ioctx)) {
/* truncating is ok because it's a user address */
ret = put_user((u32)ioctx->user_id, ctx32p);
if (ret)
kill_ioctx(current->mm, ioctx, NULL);
percpu_ref_put(&ioctx->users);
}
out:
return ret;
}
#endif
/* sys_io_destroy:
* Destroy the aio_context specified. May cancel any outstanding
* AIOs and block on completion. Will fail with -ENOSYS if not
* implemented. May fail with -EINVAL if the context pointed to
* is invalid.
*/
SYSCALL_DEFINE1(io_destroy, aio_context_t, ctx)
{
struct kioctx *ioctx = lookup_ioctx(ctx);
if (likely(NULL != ioctx)) {
struct ctx_rq_wait wait;
int ret;
init_completion(&wait.comp);
atomic_set(&wait.count, 1);
/* Pass requests_done to kill_ioctx() where it can be set
* in a thread-safe way. If we try to set it here then we have
* a race condition if two io_destroy() called simultaneously.
*/
ret = kill_ioctx(current->mm, ioctx, &wait);
percpu_ref_put(&ioctx->users);
/* Wait until all IO for the context are done. Otherwise kernel
* keep using user-space buffers even if user thinks the context
* is destroyed.
*/
if (!ret)
wait_for_completion(&wait.comp);
return ret;
}
pr_debug("EINVAL: invalid context id\n");
return -EINVAL;
}
static void aio_remove_iocb(struct aio_kiocb *iocb)
{
struct kioctx *ctx = iocb->ki_ctx;
unsigned long flags;
spin_lock_irqsave(&ctx->ctx_lock, flags);
list_del(&iocb->ki_list);
spin_unlock_irqrestore(&ctx->ctx_lock, flags);
}
static void aio_complete_rw(struct kiocb *kiocb, long res, long res2)
{
struct aio_kiocb *iocb = container_of(kiocb, struct aio_kiocb, rw);
if (!list_empty_careful(&iocb->ki_list))
aio_remove_iocb(iocb);
if (kiocb->ki_flags & IOCB_WRITE) {
struct inode *inode = file_inode(kiocb->ki_filp);
/*
* Tell lockdep we inherited freeze protection from submission
* thread.
*/
if (S_ISREG(inode->i_mode))
__sb_writers_acquired(inode->i_sb, SB_FREEZE_WRITE);
file_end_write(kiocb->ki_filp);
}
iocb->ki_res.res = res;
iocb->ki_res.res2 = res2;
iocb_put(iocb);
}
static int aio_prep_rw(struct kiocb *req, const struct iocb *iocb)
{
int ret;
req->ki_complete = aio_complete_rw;
req->private = NULL;
req->ki_pos = iocb->aio_offset;
req->ki_flags = iocb_flags(req->ki_filp) | IOCB_AIO_RW;
if (iocb->aio_flags & IOCB_FLAG_RESFD)
req->ki_flags |= IOCB_EVENTFD;
req->ki_hint = ki_hint_validate(file_write_hint(req->ki_filp));
if (iocb->aio_flags & IOCB_FLAG_IOPRIO) {
/*
* If the IOCB_FLAG_IOPRIO flag of aio_flags is set, then
* aio_reqprio is interpreted as an I/O scheduling
* class and priority.
*/
ret = ioprio_check_cap(iocb->aio_reqprio);
if (ret) {
pr_debug("aio ioprio check cap error: %d\n", ret);
return ret;
}
req->ki_ioprio = iocb->aio_reqprio;
} else
req->ki_ioprio = get_current_ioprio();
ret = kiocb_set_rw_flags(req, iocb->aio_rw_flags);
if (unlikely(ret))
return ret;
req->ki_flags &= ~IOCB_HIPRI; /* no one is going to poll for this I/O */
return 0;
}
static ssize_t aio_setup_rw(int rw, const struct iocb *iocb,
struct iovec **iovec, bool vectored, bool compat,
struct iov_iter *iter)
{
void __user *buf = (void __user *)(uintptr_t)iocb->aio_buf;
size_t len = iocb->aio_nbytes;
if (!vectored) {
ssize_t ret = import_single_range(rw, buf, len, *iovec, iter);
*iovec = NULL;
return ret;
}
#ifdef CONFIG_COMPAT
if (compat)
return compat_import_iovec(rw, buf, len, UIO_FASTIOV, iovec,
iter);
#endif
return import_iovec(rw, buf, len, UIO_FASTIOV, iovec, iter);
}
static inline void aio_rw_done(struct kiocb *req, ssize_t ret)
{
switch (ret) {
case -EIOCBQUEUED:
break;
case -ERESTARTSYS:
case -ERESTARTNOINTR:
case -ERESTARTNOHAND:
case -ERESTART_RESTARTBLOCK:
/*
* There's no easy way to restart the syscall since other AIO's
* may be already running. Just fail this IO with EINTR.
*/
ret = -EINTR;
/*FALLTHRU*/
default:
req->ki_complete(req, ret, 0);
}
}
static int aio_read(struct kiocb *req, const struct iocb *iocb,
bool vectored, bool compat)
{
struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs;
struct iov_iter iter;
struct file *file;
int ret;
ret = aio_prep_rw(req, iocb);
if (ret)
return ret;
file = req->ki_filp;
if (unlikely(!(file->f_mode & FMODE_READ)))
return -EBADF;
ret = -EINVAL;
if (unlikely(!file->f_op->read_iter))
return -EINVAL;
ret = aio_setup_rw(READ, iocb, &iovec, vectored, compat, &iter);
if (ret < 0)
return ret;
ret = rw_verify_area(READ, file, &req->ki_pos, iov_iter_count(&iter));
if (!ret)
aio_rw_done(req, call_read_iter(file, req, &iter));
kfree(iovec);
return ret;
}
static int aio_write(struct kiocb *req, const struct iocb *iocb,
bool vectored, bool compat)
{
struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs;
struct iov_iter iter;
struct file *file;
int ret;
ret = aio_prep_rw(req, iocb);
if (ret)
return ret;
file = req->ki_filp;
if (unlikely(!(file->f_mode & FMODE_WRITE)))
return -EBADF;
if (unlikely(!file->f_op->write_iter))
return -EINVAL;
ret = aio_setup_rw(WRITE, iocb, &iovec, vectored, compat, &iter);
if (ret < 0)
return ret;
ret = rw_verify_area(WRITE, file, &req->ki_pos, iov_iter_count(&iter));
if (!ret) {
/*
* Open-code file_start_write here to grab freeze protection,
* which will be released by another thread in
* aio_complete_rw(). Fool lockdep by telling it the lock got
* released so that it doesn't complain about the held lock when
* we return to userspace.
*/
if (S_ISREG(file_inode(file)->i_mode)) {
__sb_start_write(file_inode(file)->i_sb, SB_FREEZE_WRITE, true);
__sb_writers_release(file_inode(file)->i_sb, SB_FREEZE_WRITE);
}
req->ki_flags |= IOCB_WRITE;
aio_rw_done(req, call_write_iter(file, req, &iter));
}
kfree(iovec);
return ret;
}
static void aio_fsync_work(struct work_struct *work)
{
struct aio_kiocb *iocb = container_of(work, struct aio_kiocb, fsync.work);
const struct cred *old_cred = override_creds(iocb->fsync.creds);
iocb->ki_res.res = vfs_fsync(iocb->fsync.file, iocb->fsync.datasync);
revert_creds(old_cred);
put_cred(iocb->fsync.creds);
iocb_put(iocb);
}
static int aio_fsync(struct fsync_iocb *req, const struct iocb *iocb,
bool datasync)
{
if (unlikely(iocb->aio_buf || iocb->aio_offset || iocb->aio_nbytes ||
iocb->aio_rw_flags))
return -EINVAL;
if (unlikely(!req->file->f_op->fsync))
return -EINVAL;
req->creds = prepare_creds();
if (!req->creds)
return -ENOMEM;
req->datasync = datasync;
INIT_WORK(&req->work, aio_fsync_work);
schedule_work(&req->work);
return 0;
}
static void aio_poll_put_work(struct work_struct *work)
{
struct poll_iocb *req = container_of(work, struct poll_iocb, work);
struct aio_kiocb *iocb = container_of(req, struct aio_kiocb, poll);
iocb_put(iocb);
}
/*
* Safely lock the waitqueue which the request is on, synchronizing with the
* case where the ->poll() provider decides to free its waitqueue early.
*
* Returns true on success, meaning that req->head->lock was locked, req->wait
* is on req->head, and an RCU read lock was taken. Returns false if the
* request was already removed from its waitqueue (which might no longer exist).
*/
static bool poll_iocb_lock_wq(struct poll_iocb *req)
{
wait_queue_head_t *head;
/*
* While we hold the waitqueue lock and the waitqueue is nonempty,
* wake_up_pollfree() will wait for us. However, taking the waitqueue
* lock in the first place can race with the waitqueue being freed.
*
* We solve this as eventpoll does: by taking advantage of the fact that
* all users of wake_up_pollfree() will RCU-delay the actual free. If
* we enter rcu_read_lock() and see that the pointer to the queue is
* non-NULL, we can then lock it without the memory being freed out from
* under us, then check whether the request is still on the queue.
*
* Keep holding rcu_read_lock() as long as we hold the queue lock, in
* case the caller deletes the entry from the queue, leaving it empty.
* In that case, only RCU prevents the queue memory from being freed.
*/
rcu_read_lock();
head = smp_load_acquire(&req->head);
if (head) {
spin_lock(&head->lock);
if (!list_empty(&req->wait.entry))
return true;
spin_unlock(&head->lock);
}
rcu_read_unlock();
return false;
}
static void poll_iocb_unlock_wq(struct poll_iocb *req)
{
spin_unlock(&req->head->lock);
rcu_read_unlock();
}
static void aio_poll_complete_work(struct work_struct *work)
{
struct poll_iocb *req = container_of(work, struct poll_iocb, work);
struct aio_kiocb *iocb = container_of(req, struct aio_kiocb, poll);
struct poll_table_struct pt = { ._key = req->events };
struct kioctx *ctx = iocb->ki_ctx;
__poll_t mask = 0;
if (!READ_ONCE(req->cancelled))
mask = vfs_poll(req->file, &pt) & req->events;
/*
* Note that ->ki_cancel callers also delete iocb from active_reqs after
* calling ->ki_cancel. We need the ctx_lock roundtrip here to
* synchronize with them. In the cancellation case the list_del_init
* itself is not actually needed, but harmless so we keep it in to
* avoid further branches in the fast path.
*/
spin_lock_irq(&ctx->ctx_lock);
if (poll_iocb_lock_wq(req)) {
if (!mask && !READ_ONCE(req->cancelled)) {
/*
* The request isn't actually ready to be completed yet.
* Reschedule completion if another wakeup came in.
*/
if (req->work_need_resched) {
schedule_work(&req->work);
req->work_need_resched = false;
} else {
req->work_scheduled = false;
}
poll_iocb_unlock_wq(req);
spin_unlock_irq(&ctx->ctx_lock);
return;
}
list_del_init(&req->wait.entry);
poll_iocb_unlock_wq(req);
} /* else, POLLFREE has freed the waitqueue, so we must complete */
list_del_init(&iocb->ki_list);
iocb->ki_res.res = mangle_poll(mask);
spin_unlock_irq(&ctx->ctx_lock);
iocb_put(iocb);
}
/* assumes we are called with irqs disabled */
static int aio_poll_cancel(struct kiocb *iocb)
{
struct aio_kiocb *aiocb = container_of(iocb, struct aio_kiocb, rw);
struct poll_iocb *req = &aiocb->poll;
if (poll_iocb_lock_wq(req)) {
WRITE_ONCE(req->cancelled, true);
if (!req->work_scheduled) {
schedule_work(&aiocb->poll.work);
req->work_scheduled = true;
}
poll_iocb_unlock_wq(req);
} /* else, the request was force-cancelled by POLLFREE already */
return 0;
}
static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
void *key)
{
struct poll_iocb *req = container_of(wait, struct poll_iocb, wait);
struct aio_kiocb *iocb = container_of(req, struct aio_kiocb, poll);
__poll_t mask = key_to_poll(key);
unsigned long flags;
/* for instances that support it check for an event match first: */
if (mask && !(mask & req->events))
return 0;
/*
* Complete the request inline if possible. This requires that three
* conditions be met:
* 1. An event mask must have been passed. If a plain wakeup was done
* instead, then mask == 0 and we have to call vfs_poll() to get
* the events, so inline completion isn't possible.
* 2. The completion work must not have already been scheduled.
* 3. ctx_lock must not be busy. We have to use trylock because we
* already hold the waitqueue lock, so this inverts the normal
* locking order. Use irqsave/irqrestore because not all
* filesystems (e.g. fuse) call this function with IRQs disabled,
* yet IRQs have to be disabled before ctx_lock is obtained.
*/
if (mask && !req->work_scheduled &&
spin_trylock_irqsave(&iocb->ki_ctx->ctx_lock, flags)) {
struct kioctx *ctx = iocb->ki_ctx;
list_del_init(&req->wait.entry);
list_del(&iocb->ki_list);
iocb->ki_res.res = mangle_poll(mask);
if (iocb->ki_eventfd && eventfd_signal_count()) {
iocb = NULL;
INIT_WORK(&req->work, aio_poll_put_work);
schedule_work(&req->work);
}
spin_unlock_irqrestore(&ctx->ctx_lock, flags);
if (iocb)
iocb_put(iocb);
} else {
/*
* Schedule the completion work if needed. If it was already
* scheduled, record that another wakeup came in.
*
* Don't remove the request from the waitqueue here, as it might
* not actually be complete yet (we won't know until vfs_poll()
* is called), and we must not miss any wakeups. POLLFREE is an
* exception to this; see below.
*/
if (req->work_scheduled) {
req->work_need_resched = true;
} else {
schedule_work(&req->work);
req->work_scheduled = true;
}
/*
* If the waitqueue is being freed early but we can't complete
* the request inline, we have to tear down the request as best
* we can. That means immediately removing the request from its
* waitqueue and preventing all further accesses to the
* waitqueue via the request. We also need to schedule the
* completion work (done above). Also mark the request as
* cancelled, to potentially skip an unneeded call to ->poll().
*/
if (mask & POLLFREE) {
WRITE_ONCE(req->cancelled, true);
list_del_init(&req->wait.entry);
/*
* Careful: this *must* be the last step, since as soon
* as req->head is NULL'ed out, the request can be
* completed and freed, since aio_poll_complete_work()
* will no longer need to take the waitqueue lock.
*/
smp_store_release(&req->head, NULL);
}
}
return 1;
}
struct aio_poll_table {
struct poll_table_struct pt;
struct aio_kiocb *iocb;
bool queued;
int error;
};
static void
aio_poll_queue_proc(struct file *file, struct wait_queue_head *head,
struct poll_table_struct *p)
{
struct aio_poll_table *pt = container_of(p, struct aio_poll_table, pt);
/* multiple wait queues per file are not supported */
if (unlikely(pt->queued)) {
pt->error = -EINVAL;
return;
}
pt->queued = true;
pt->error = 0;
pt->iocb->poll.head = head;
add_wait_queue(head, &pt->iocb->poll.wait);
}
static int aio_poll(struct aio_kiocb *aiocb, const struct iocb *iocb)
{
struct kioctx *ctx = aiocb->ki_ctx;
struct poll_iocb *req = &aiocb->poll;
struct aio_poll_table apt;
bool cancel = false;
__poll_t mask;
/* reject any unknown events outside the normal event mask. */
if ((u16)iocb->aio_buf != iocb->aio_buf)
return -EINVAL;
/* reject fields that are not defined for poll */
if (iocb->aio_offset || iocb->aio_nbytes || iocb->aio_rw_flags)
return -EINVAL;
INIT_WORK(&req->work, aio_poll_complete_work);
req->events = demangle_poll(iocb->aio_buf) | EPOLLERR | EPOLLHUP;
req->head = NULL;
req->cancelled = false;
req->work_scheduled = false;
req->work_need_resched = false;
apt.pt._qproc = aio_poll_queue_proc;
apt.pt._key = req->events;
apt.iocb = aiocb;
apt.queued = false;
apt.error = -EINVAL; /* same as no support for IOCB_CMD_POLL */
/* initialized the list so that we can do list_empty checks */
INIT_LIST_HEAD(&req->wait.entry);
init_waitqueue_func_entry(&req->wait, aio_poll_wake);
mask = vfs_poll(req->file, &apt.pt) & req->events;
spin_lock_irq(&ctx->ctx_lock);
if (likely(apt.queued)) {
bool on_queue = poll_iocb_lock_wq(req);
if (!on_queue || req->work_scheduled) {
/*
* aio_poll_wake() already either scheduled the async
* completion work, or completed the request inline.
*/
if (apt.error) /* unsupported case: multiple queues */
cancel = true;
apt.error = 0;
mask = 0;
}
if (mask || apt.error) {
/* Steal to complete synchronously. */
list_del_init(&req->wait.entry);
} else if (cancel) {
/* Cancel if possible (may be too late though). */
WRITE_ONCE(req->cancelled, true);
} else if (on_queue) {
/*
* Actually waiting for an event, so add the request to
* active_reqs so that it can be cancelled if needed.
*/
list_add_tail(&aiocb->ki_list, &ctx->active_reqs);
aiocb->ki_cancel = aio_poll_cancel;
}
if (on_queue)
poll_iocb_unlock_wq(req);
}
if (mask) { /* no async, we'd stolen it */
aiocb->ki_res.res = mangle_poll(mask);
apt.error = 0;
}
spin_unlock_irq(&ctx->ctx_lock);
if (mask)
iocb_put(aiocb);
return apt.error;
}
static int __io_submit_one(struct kioctx *ctx, const struct iocb *iocb,
struct iocb __user *user_iocb, struct aio_kiocb *req,
bool compat)
{
req->ki_filp = fget(iocb->aio_fildes);
if (unlikely(!req->ki_filp))
return -EBADF;
if (iocb->aio_flags & IOCB_FLAG_RESFD) {
struct eventfd_ctx *eventfd;
/*
* If the IOCB_FLAG_RESFD flag of aio_flags is set, get an
* instance of the file* now. The file descriptor must be
* an eventfd() fd, and will be signaled for each completed
* event using the eventfd_signal() function.
*/
eventfd = eventfd_ctx_fdget(iocb->aio_resfd);
if (IS_ERR(eventfd))
return PTR_ERR(eventfd);
req->ki_eventfd = eventfd;
}
if (unlikely(put_user(KIOCB_KEY, &user_iocb->aio_key))) {
pr_debug("EFAULT: aio_key\n");
return -EFAULT;
}
req->ki_res.obj = (u64)(unsigned long)user_iocb;
req->ki_res.data = iocb->aio_data;
req->ki_res.res = 0;
req->ki_res.res2 = 0;
switch (iocb->aio_lio_opcode) {
case IOCB_CMD_PREAD:
return aio_read(&req->rw, iocb, false, compat);
case IOCB_CMD_PWRITE:
return aio_write(&req->rw, iocb, false, compat);
case IOCB_CMD_PREADV:
return aio_read(&req->rw, iocb, true, compat);
case IOCB_CMD_PWRITEV:
return aio_write(&req->rw, iocb, true, compat);
case IOCB_CMD_FSYNC:
return aio_fsync(&req->fsync, iocb, false);
case IOCB_CMD_FDSYNC:
return aio_fsync(&req->fsync, iocb, true);
case IOCB_CMD_POLL:
return aio_poll(req, iocb);
default:
pr_debug("invalid aio operation %d\n", iocb->aio_lio_opcode);
return -EINVAL;
}
}
static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
bool compat)
{
struct aio_kiocb *req;
struct iocb iocb;
int err;
if (unlikely(copy_from_user(&iocb, user_iocb, sizeof(iocb))))
return -EFAULT;
/* enforce forwards compatibility on users */
if (unlikely(iocb.aio_reserved2)) {
pr_debug("EINVAL: reserve field set\n");
return -EINVAL;
}
/* prevent overflows */
if (unlikely(
(iocb.aio_buf != (unsigned long)iocb.aio_buf) ||
(iocb.aio_nbytes != (size_t)iocb.aio_nbytes) ||
((ssize_t)iocb.aio_nbytes < 0)
)) {
pr_debug("EINVAL: overflow check\n");
return -EINVAL;
}
req = aio_get_req(ctx);
if (unlikely(!req))
return -EAGAIN;
err = __io_submit_one(ctx, &iocb, user_iocb, req, compat);
/* Done with the synchronous reference */
iocb_put(req);
/*
* If err is 0, we'd either done aio_complete() ourselves or have
* arranged for that to be done asynchronously. Anything non-zero
* means that we need to destroy req ourselves.
*/
if (unlikely(err)) {
iocb_destroy(req);
put_reqs_available(ctx, 1);
}
return err;
}
/* sys_io_submit:
* Queue the nr iocbs pointed to by iocbpp for processing. Returns
* the number of iocbs queued. May return -EINVAL if the aio_context
* specified by ctx_id is invalid, if nr is < 0, if the iocb at
* *iocbpp[0] is not properly initialized, if the operation specified
* is invalid for the file descriptor in the iocb. May fail with
* -EFAULT if any of the data structures point to invalid data. May
* fail with -EBADF if the file descriptor specified in the first
* iocb is invalid. May fail with -EAGAIN if insufficient resources
* are available to queue any iocbs. Will return 0 if nr is 0. Will
* fail with -ENOSYS if not implemented.
*/
SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr,
struct iocb __user * __user *, iocbpp)
{
struct kioctx *ctx;
long ret = 0;
int i = 0;
struct blk_plug plug;
if (unlikely(nr < 0))
return -EINVAL;
ctx = lookup_ioctx(ctx_id);
if (unlikely(!ctx)) {
pr_debug("EINVAL: invalid context id\n");
return -EINVAL;
}
if (nr > ctx->nr_events)
nr = ctx->nr_events;
blk_start_plug(&plug);
for (i = 0; i < nr; i++) {
struct iocb __user *user_iocb;
if (unlikely(get_user(user_iocb, iocbpp + i))) {
ret = -EFAULT;
break;
}
ret = io_submit_one(ctx, user_iocb, false);
if (ret)
break;
}
blk_finish_plug(&plug);
percpu_ref_put(&ctx->users);
return i ? i : ret;
}
#ifdef CONFIG_COMPAT
COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id,
int, nr, compat_uptr_t __user *, iocbpp)
{
struct kioctx *ctx;
long ret = 0;
int i = 0;
struct blk_plug plug;
if (unlikely(nr < 0))
return -EINVAL;
ctx = lookup_ioctx(ctx_id);
if (unlikely(!ctx)) {
pr_debug("EINVAL: invalid context id\n");
return -EINVAL;
}
if (nr > ctx->nr_events)
nr = ctx->nr_events;
blk_start_plug(&plug);
for (i = 0; i < nr; i++) {
compat_uptr_t user_iocb;
if (unlikely(get_user(user_iocb, iocbpp + i))) {
ret = -EFAULT;
break;
}
ret = io_submit_one(ctx, compat_ptr(user_iocb), true);
if (ret)
break;
}
blk_finish_plug(&plug);
percpu_ref_put(&ctx->users);
return i ? i : ret;
}
#endif
/* sys_io_cancel:
* Attempts to cancel an iocb previously passed to io_submit. If
* the operation is successfully cancelled, the resulting event is
* copied into the memory pointed to by result without being placed
* into the completion queue and 0 is returned. May fail with
* -EFAULT if any of the data structures pointed to are invalid.
* May fail with -EINVAL if aio_context specified by ctx_id is
* invalid. May fail with -EAGAIN if the iocb specified was not
* cancelled. Will fail with -ENOSYS if not implemented.
*/
SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb,
struct io_event __user *, result)
{
struct kioctx *ctx;
struct aio_kiocb *kiocb;
int ret = -EINVAL;
u32 key;
u64 obj = (u64)(unsigned long)iocb;
if (unlikely(get_user(key, &iocb->aio_key)))
return -EFAULT;
if (unlikely(key != KIOCB_KEY))
return -EINVAL;
ctx = lookup_ioctx(ctx_id);
if (unlikely(!ctx))
return -EINVAL;
spin_lock_irq(&ctx->ctx_lock);
/* TODO: use a hash or array, this sucks. */
list_for_each_entry(kiocb, &ctx->active_reqs, ki_list) {
if (kiocb->ki_res.obj == obj) {
ret = kiocb->ki_cancel(&kiocb->rw);
list_del_init(&kiocb->ki_list);
break;
}
}
spin_unlock_irq(&ctx->ctx_lock);
if (!ret) {
/*
* The result argument is no longer used - the io_event is
* always delivered via the ring buffer. -EINPROGRESS indicates
* cancellation is progress:
*/
ret = -EINPROGRESS;
}
percpu_ref_put(&ctx->users);
return ret;
}
static long do_io_getevents(aio_context_t ctx_id,
long min_nr,
long nr,
struct io_event __user *events,
struct timespec64 *ts)
{
ktime_t until = ts ? timespec64_to_ktime(*ts) : KTIME_MAX;
struct kioctx *ioctx = lookup_ioctx(ctx_id);
long ret = -EINVAL;
if (likely(ioctx)) {
if (likely(min_nr <= nr && min_nr >= 0))
ret = read_events(ioctx, min_nr, nr, events, until);
percpu_ref_put(&ioctx->users);
}
return ret;
}
/* io_getevents:
* Attempts to read at least min_nr events and up to nr events from
* the completion queue for the aio_context specified by ctx_id. If
* it succeeds, the number of read events is returned. May fail with
* -EINVAL if ctx_id is invalid, if min_nr is out of range, if nr is
* out of range, if timeout is out of range. May fail with -EFAULT
* if any of the memory specified is invalid. May return 0 or
* < min_nr if the timeout specified by timeout has elapsed
* before sufficient events are available, where timeout == NULL
* specifies an infinite timeout. Note that the timeout pointed to by
* timeout is relative. Will fail with -ENOSYS if not implemented.
*/
#if !defined(CONFIG_64BIT_TIME) || defined(CONFIG_64BIT)
SYSCALL_DEFINE5(io_getevents, aio_context_t, ctx_id,
long, min_nr,
long, nr,
struct io_event __user *, events,
struct __kernel_timespec __user *, timeout)
{
struct timespec64 ts;
int ret;
if (timeout && unlikely(get_timespec64(&ts, timeout)))
return -EFAULT;
ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &ts : NULL);
if (!ret && signal_pending(current))
ret = -EINTR;
return ret;
}
#endif
struct __aio_sigset {
const sigset_t __user *sigmask;
size_t sigsetsize;
};
SYSCALL_DEFINE6(io_pgetevents,
aio_context_t, ctx_id,
long, min_nr,
long, nr,
struct io_event __user *, events,
struct __kernel_timespec __user *, timeout,
const struct __aio_sigset __user *, usig)
{
struct __aio_sigset ksig = { NULL, };
struct timespec64 ts;
bool interrupted;
int ret;
if (timeout && unlikely(get_timespec64(&ts, timeout)))
return -EFAULT;
if (usig && copy_from_user(&ksig, usig, sizeof(ksig)))
return -EFAULT;
ret = set_user_sigmask(ksig.sigmask, ksig.sigsetsize);
if (ret)
return ret;
ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &ts : NULL);
interrupted = signal_pending(current);
restore_saved_sigmask_unless(interrupted);
if (interrupted && !ret)
ret = -ERESTARTNOHAND;
return ret;
}
#if defined(CONFIG_COMPAT_32BIT_TIME) && !defined(CONFIG_64BIT)
SYSCALL_DEFINE6(io_pgetevents_time32,
aio_context_t, ctx_id,
long, min_nr,
long, nr,
struct io_event __user *, events,
struct old_timespec32 __user *, timeout,
const struct __aio_sigset __user *, usig)
{
struct __aio_sigset ksig = { NULL, };
struct timespec64 ts;
bool interrupted;
int ret;
if (timeout && unlikely(get_old_timespec32(&ts, timeout)))
return -EFAULT;
if (usig && copy_from_user(&ksig, usig, sizeof(ksig)))
return -EFAULT;
ret = set_user_sigmask(ksig.sigmask, ksig.sigsetsize);
if (ret)
return ret;
ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &ts : NULL);
interrupted = signal_pending(current);
restore_saved_sigmask_unless(interrupted);
if (interrupted && !ret)
ret = -ERESTARTNOHAND;
return ret;
}
#endif
#if defined(CONFIG_COMPAT_32BIT_TIME)
SYSCALL_DEFINE5(io_getevents_time32, __u32, ctx_id,
__s32, min_nr,
__s32, nr,
struct io_event __user *, events,
struct old_timespec32 __user *, timeout)
{
struct timespec64 t;
int ret;
if (timeout && get_old_timespec32(&t, timeout))
return -EFAULT;
ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &t : NULL);
if (!ret && signal_pending(current))
ret = -EINTR;
return ret;
}
#endif
#ifdef CONFIG_COMPAT
struct __compat_aio_sigset {
compat_uptr_t sigmask;
compat_size_t sigsetsize;
};
#if defined(CONFIG_COMPAT_32BIT_TIME)
COMPAT_SYSCALL_DEFINE6(io_pgetevents,
compat_aio_context_t, ctx_id,
compat_long_t, min_nr,
compat_long_t, nr,
struct io_event __user *, events,
struct old_timespec32 __user *, timeout,
const struct __compat_aio_sigset __user *, usig)
{
struct __compat_aio_sigset ksig = { 0, };
struct timespec64 t;
bool interrupted;
int ret;
if (timeout && get_old_timespec32(&t, timeout))
return -EFAULT;
if (usig && copy_from_user(&ksig, usig, sizeof(ksig)))
return -EFAULT;
ret = set_compat_user_sigmask(compat_ptr(ksig.sigmask), ksig.sigsetsize);
if (ret)
return ret;
ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &t : NULL);
interrupted = signal_pending(current);
restore_saved_sigmask_unless(interrupted);
if (interrupted && !ret)
ret = -ERESTARTNOHAND;
return ret;
}
#endif
COMPAT_SYSCALL_DEFINE6(io_pgetevents_time64,
compat_aio_context_t, ctx_id,
compat_long_t, min_nr,
compat_long_t, nr,
struct io_event __user *, events,
struct __kernel_timespec __user *, timeout,
const struct __compat_aio_sigset __user *, usig)
{
struct __compat_aio_sigset ksig = { 0, };
struct timespec64 t;
bool interrupted;
int ret;
if (timeout && get_timespec64(&t, timeout))
return -EFAULT;
if (usig && copy_from_user(&ksig, usig, sizeof(ksig)))
return -EFAULT;
ret = set_compat_user_sigmask(compat_ptr(ksig.sigmask), ksig.sigsetsize);
if (ret)
return ret;
ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &t : NULL);
interrupted = signal_pending(current);
restore_saved_sigmask_unless(interrupted);
if (interrupted && !ret)
ret = -ERESTARTNOHAND;
return ret;
}
#endif