-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAmKos2QACgkQONu9yGCS aT4QYQ//WQD/rHjO021lbo/z4eZbWUxjDiQNisJQY4MTCnIJgPYROJ6YLBLL2+of VwDdZ0yQNpf3hBA3qgTZ8RgaBinVf+WNAk37Ap/3VFXTExxgyGCx7p/PG+Jx9Jk4 qd9YPHZCu8g9rQjJoex95fd8Fedu47tzBSd88MoAKiLz90JsNbYUZb+gqdRrLAYc 6krd7zm7T8Grk31xUWOl/tlUSxveuUuz6QQr5mwPmSyspz4gQXsBlrKSrNSWmk0o qtqgqUCypvpKTF7RYiEoS3F8wy4XvWpGsET+W79SJ84inVx3EMsZKXB9GsWVZZgI fm3eFjn10NcgA+lvc7TJpwKg0f5g8uHW/06FcfYwgBhbI+otCFDLQkkHtViN0wY2 gks3PLPsYJdAZTlwIvjNY0XY7wRqjS7Ta1pf+d1po1EndEFAyH76KJaIGCzdVKb4 OeSEy4Xw8HxmuCO+mrUtRVRqV3Y7x88GuJC359iDKYdDpc+Z21FcvaVcgrR5cy2V A7ICKIfNyArgNmWnXQ6UBXqS1rDcoyfJe+0CYyRRdgDO/ON48Mx8FIW9YJrSrMeS XEx6cw6VKZ7hE1G71us/ITOOeUlHO93V7Ju+oOcx9Fgew8TZ0mdNMliOFUFaNWPb iAG+zZD0jwP5iyx0KFfOJyyuoovEtjBh9ZgVIF5BP3Ry1xRHuHY= =oE7B -----END PGP SIGNATURE----- Merge 5.4.198 into android11-5.4-lts Changes in 5.4.198 binfmt_flat: do not stop relocating GOT entries prematurely on riscv ALSA: hda/realtek - Fix microphone noise on ASUS TUF B550M-PLUS USB: serial: option: add Quectel BG95 modem USB: new quirk for Dell Gen 2 devices usb: core: hcd: Add support for deferring roothub registration perf/x86/intel: Fix event constraints for ICL ptrace/um: Replace PT_DTRACE with TIF_SINGLESTEP ptrace/xtensa: Replace PT_SINGLESTEP with TIF_SINGLESTEP ptrace: Reimplement PTRACE_KILL by always sending SIGKILL btrfs: add "0x" prefix for unsupported optional features btrfs: repair super block num_devices automatically drm/virtio: fix NULL pointer dereference in virtio_gpu_conn_get_modes mwifiex: add mutex lock for call in mwifiex_dfs_chan_sw_work_queue b43legacy: Fix assigning negative value to unsigned variable b43: Fix assigning negative value to unsigned variable ipw2x00: Fix potential NULL dereference in libipw_xmit() ipv6: fix locking issues with loops over idev->addr_list fbcon: Consistently protect deferred_takeover with console_lock() ACPICA: Avoid cache flush inside virtual machines drm/komeda: return early if drm_universal_plane_init() fails. ALSA: jack: Access input_dev under mutex spi: spi-rspi: Remove setting {src,dst}_{addr,addr_width} based on DMA direction tools/power turbostat: fix ICX DRAM power numbers drm/amd/pm: fix double free in si_parse_power_table() ath9k: fix QCA9561 PA bias level media: venus: hfi: avoid null dereference in deinit media: pci: cx23885: Fix the error handling in cx23885_initdev() media: cx25821: Fix the warning when removing the module md/bitmap: don't set sb values if can't pass sanity check mmc: jz4740: Apply DMA engine limits to maximum segment size scsi: megaraid: Fix error check return value of register_chrdev() drm/plane: Move range check for format_count earlier drm/amd/pm: fix the compile warning arm64: compat: Do not treat syscall number as ESR_ELx for a bad syscall drm: msm: fix error check return value of irq_of_parse_and_map() ipv6: Don't send rs packets to the interface of ARPHRD_TUNNEL net/mlx5: fs, delete the FTE when there are no rules attached to it ASoC: dapm: Don't fold register value changes into notifications mlxsw: spectrum_dcb: Do not warn about priority changes drm/amdgpu/ucode: Remove firmware load type check in amdgpu_ucode_free_bo HID: bigben: fix slab-out-of-bounds Write in bigben_probe ASoC: tscs454: Add endianness flag in snd_soc_component_driver s390/preempt: disable __preempt_count_add() optimization for PROFILE_ALL_BRANCHES spi: stm32-qspi: Fix wait_cmd timeout in APM mode dma-debug: change allocation mode from GFP_NOWAIT to GFP_ATIOMIC ACPI: PM: Block ASUS B1400CEAE from suspend to idle by default ipmi:ssif: Check for NULL msg when handling events and messages ipmi: Fix pr_fmt to avoid compilation issues rtlwifi: Use pr_warn instead of WARN_ONCE media: coda: limit frame interval enumeration to supported encoder frame sizes media: cec-adap.c: fix is_configuring state openrisc: start CPU timer early in boot nvme-pci: fix a NULL pointer dereference in nvme_alloc_admin_tags ASoC: rt5645: Fix errorenous cleanup order nbd: Fix hung on disconnect request if socket is closed before net: phy: micrel: Allow probing without .driver_data media: exynos4-is: Fix compile warning ASoC: max98357a: remove dependency on GPIOLIB hwmon: Make chip parameter for with_info API mandatory rxrpc: Return an error to sendmsg if call failed eth: tg3: silence the GCC 12 array-bounds warning selftests/bpf: fix btf_dump/btf_dump due to recent clang change IB/rdmavt: add missing locks in rvt_ruc_loopback ARM: dts: ox820: align interrupt controller node name with dtschema PM / devfreq: rk3399_dmc: Disable edev on remove() fs: jfs: fix possible NULL pointer dereference in dbFree() ARM: OMAP1: clock: Fix UART rate reporting algorithm powerpc/fadump: Fix fadump to work with a different endian capture kernel fat: add ratelimit to fat*_ent_bread() ARM: versatile: Add missing of_node_put in dcscb_init ARM: dts: exynos: add atmel,24c128 fallback to Samsung EEPROM ARM: hisi: Add missing of_node_put after of_find_compatible_node PCI: Avoid pci_dev_lock() AB/BA deadlock with sriov_numvfs_store() tracing: incorrect isolate_mote_t cast in mm_vmscan_lru_isolate powerpc/xics: fix refcount leak in icp_opal_init() powerpc/powernv: fix missing of_node_put in uv_init() macintosh/via-pmu: Fix build failure when CONFIG_INPUT is disabled powerpc/iommu: Add missing of_node_put in iommu_init_early_dart RDMA/hfi1: Prevent panic when SDMA is disabled drm: fix EDID struct for old ARM OABI format ath9k: fix ar9003_get_eepmisc drm/edid: fix invalid EDID extension block filtering drm/bridge: adv7511: clean up CEC adapter when probe fails ASoC: mediatek: Fix error handling in mt8173_max98090_dev_probe ASoC: mediatek: Fix missing of_node_put in mt2701_wm8960_machine_probe x86/delay: Fix the wrong asm constraint in delay_loop() drm/mediatek: Fix mtk_cec_mask() drm/vc4: txp: Don't set TXP_VSTART_AT_EOF drm/vc4: txp: Force alpha to be 0xff if it's disabled bpf: Fix excessive memory allocation in stack_map_alloc() nl80211: show SSID for P2P_GO interfaces drm/komeda: Fix an undefined behavior bug in komeda_plane_add() drm: mali-dp: potential dereference of null pointer spi: spi-ti-qspi: Fix return value handling of wait_for_completion_timeout NFC: NULL out the dev->rfkill to prevent UAF efi: Add missing prototype for efi_capsule_setup_info drbd: fix duplicate array initializer HID: hid-led: fix maximum brightness for Dream Cheeky HID: elan: Fix potential double free in elan_input_configured drm/bridge: Fix error handling in analogix_dp_probe sched/fair: Fix cfs_rq_clock_pelt() for throttled cfs_rq spi: img-spfi: Fix pm_runtime_get_sync() error checking cpufreq: Fix possible race in cpufreq online error path ath9k_htc: fix potential out of bounds access with invalid rxstatus->rs_keyix inotify: show inotify mask flags in proc fdinfo fsnotify: fix wrong lockdep annotations of: overlay: do not break notify on NOTIFY_{OK|STOP} scsi: ufs: core: Exclude UECxx from SFR dump list x86/pm: Fix false positive kmemleak report in msr_build_context() x86/speculation: Add missing prototype for unpriv_ebpf_notify() ASoC: rk3328: fix disabling mclk on pclk probe failure perf tools: Add missing headers needed by util/data.h drm/msm/disp/dpu1: set vbif hw config to NULL to avoid use after memory free during pm runtime resume drm/msm/dsi: fix error checks and return values for DSI xmit functions drm/msm/hdmi: check return value after calling platform_get_resource_byname() drm/msm/hdmi: fix error check return value of irq_of_parse_and_map() drm/rockchip: vop: fix possible null-ptr-deref in vop_bind() virtio_blk: fix the discard_granularity and discard_alignment queue limits x86: Fix return value of __setup handlers irqchip/exiu: Fix acknowledgment of edge triggered interrupts irqchip/aspeed-i2c-ic: Fix irq_of_parse_and_map() return value x86/mm: Cleanup the control_va_addr_alignment() __setup handler regulator: core: Fix enable_count imbalance with EXCLUSIVE_GET drm/msm/mdp5: Return error code in mdp5_pipe_release when deadlock is detected drm/msm/mdp5: Return error code in mdp5_mixer_release when deadlock is detected drm/msm: return an error pointer in msm_gem_prime_get_sg_table() media: uvcvideo: Fix missing check to determine if element is found in list iomap: iomap_write_failed fix Revert "cpufreq: Fix possible race in cpufreq online error path" perf/amd/ibs: Use interrupt regs ip for stack unwinding ASoC: fsl: Fix refcount leak in imx_sgtl5000_probe ASoC: mxs-saif: Fix refcount leak in mxs_saif_probe regulator: pfuze100: Fix refcount leak in pfuze_parse_regulators_dt scripts/faddr2line: Fix overlapping text section failures media: aspeed: Fix an error handling path in aspeed_video_probe() media: st-delta: Fix PM disable depth imbalance in delta_probe media: exynos4-is: Change clk_disable to clk_disable_unprepare media: pvrusb2: fix array-index-out-of-bounds in pvr2_i2c_core_init media: vsp1: Fix offset calculation for plane cropping Bluetooth: fix dangling sco_conn and use-after-free in sco_sock_timeout m68k: math-emu: Fix dependencies of math emulation support sctp: read sk->sk_bound_dev_if once in sctp_rcv() media: ov7670: remove ov7670_power_off from ov7670_remove ext4: reject the 'commit' option on ext2 filesystems drm/msm/a6xx: Fix refcount leak in a6xx_gpu_init drm: msm: fix possible memory leak in mdp5_crtc_cursor_set() thermal/drivers/broadcom: Fix potential NULL dereference in sr_thermal_probe ASoC: wm2000: fix missing clk_disable_unprepare() on error in wm2000_anc_transition() NFC: hci: fix sleep in atomic context bugs in nfc_hci_hcp_message_tx rxrpc: Fix listen() setting the bar too high for the prealloc rings rxrpc: Don't try to resend the request if we're receiving the reply rxrpc: Fix overlapping ACK accounting rxrpc: Don't let ack.previousPacket regress rxrpc: Fix decision on when to generate an IDLE ACK net/smc: postpone sk_refcnt increment in connect() arm64: dts: rockchip: Move drive-impedance-ohm to emmc phy on rk3399 ARM: dts: suniv: F1C100: fix watchdog compatible soc: qcom: smp2p: Fix missing of_node_put() in smp2p_parse_ipc soc: qcom: smsm: Fix missing of_node_put() in smsm_parse_ipc PCI: cadence: Fix find_first_zero_bit() limit PCI: rockchip: Fix find_first_zero_bit() limit KVM: nVMX: Leave most VM-Exit info fields unmodified on failed VM-Entry can: xilinx_can: mark bit timing constants as const ARM: dts: bcm2835-rpi-zero-w: Fix GPIO line name for Wifi/BT ARM: dts: bcm2837-rpi-cm3-io3: Fix GPIO line names for SMPS I2C ARM: dts: bcm2837-rpi-3-b-plus: Fix GPIO line name of power LED ARM: dts: bcm2835-rpi-b: Fix GPIO line names misc: ocxl: fix possible double free in ocxl_file_register_afu crypto: marvell/cesa - ECB does not IV arm: mediatek: select arch timer for mt7629 powerpc/fadump: fix PT_LOAD segment for boot memory area mfd: ipaq-micro: Fix error check return value of platform_get_irq() scsi: fcoe: Fix Wstringop-overflow warnings in fcoe_wwn_from_mac() firmware: arm_scmi: Fix list protocols enumeration in the base protocol nvdimm: Allow overwrite in the presence of disabled dimms pinctrl: mvebu: Fix irq_of_parse_and_map() return value drivers/base/node.c: fix compaction sysfs file leak dax: fix cache flush on PMD-mapped pages powerpc/8xx: export 'cpm_setbrg' for modules powerpc/idle: Fix return value of __setup() handler powerpc/4xx/cpm: Fix return value of __setup() handler proc: fix dentry/inode overinstantiating under /proc/${pid}/net ipc/mqueue: use get_tree_nodev() in mqueue_get_tree() PCI: imx6: Fix PERST# start-up sequence tty: fix deadlock caused by calling printk() under tty_port->lock crypto: cryptd - Protect per-CPU resource by disabling BH. Input: sparcspkr - fix refcount leak in bbc_beep_probe powerpc/64: Only WARN if __pa()/__va() called with bad addresses powerpc/perf: Fix the threshold compare group constraint for power9 macintosh: via-pmu and via-cuda need RTC_LIB powerpc/fsl_rio: Fix refcount leak in fsl_rio_setup mfd: davinci_voicecodec: Fix possible null-ptr-deref davinci_vc_probe() mailbox: forward the hrtimer if not queued and under a lock RDMA/hfi1: Prevent use of lock before it is initialized Input: stmfts - do not leave device disabled in stmfts_input_open f2fs: fix dereference of stale list iterator after loop body iommu/mediatek: Add list_del in mtk_iommu_remove i2c: at91: use dma safe buffers i2c: at91: Initialize dma_buf in at91_twi_xfer() NFS: Do not report EINTR/ERESTARTSYS as mapping errors NFS: Do not report flush errors in nfs_write_end() NFS: Don't report errors from nfs_pageio_complete() more than once NFSv4/pNFS: Do not fail I/O when we fail to allocate the pNFS layout video: fbdev: clcdfb: Fix refcount leak in clcdfb_of_vram_setup dmaengine: stm32-mdma: remove GISR1 register iommu/amd: Increase timeout waiting for GA log enablement perf c2c: Use stdio interface if slang is not supported perf jevents: Fix event syntax error caused by ExtSel f2fs: fix to avoid f2fs_bug_on() in dec_valid_node_count() f2fs: fix to do sanity check on block address in f2fs_do_zero_range() f2fs: fix to clear dirty inode in f2fs_evict_inode() f2fs: fix deadloop in foreground GC f2fs: don't need inode lock for system hidden quota f2fs: fix fallocate to use file_modified to update permissions consistently wifi: mac80211: fix use-after-free in chanctx code iwlwifi: mvm: fix assert 1F04 upon reconfig fs-writeback: writeback_sb_inodes:Recalculate 'wrote' according skipped pages efi: Do not import certificates from UEFI Secure Boot for T2 Macs bfq: Split shared queues on move between cgroups bfq: Update cgroup information before merging bio bfq: Track whether bfq_group is still online netfilter: nf_tables: disallow non-stateful expression in sets earlier ext4: fix use-after-free in ext4_rename_dir_prepare ext4: fix warning in ext4_handle_inode_extension ext4: fix bug_on in ext4_writepages ext4: verify dir block before splitting it ext4: avoid cycles in directory h-tree ACPI: property: Release subnode properties with data nodes tracing: Fix potential double free in create_var_ref() PCI/PM: Fix bridge_d3_blacklist[] Elo i2 overwrite of Gigabyte X299 PCI: qcom: Fix runtime PM imbalance on probe errors PCI: qcom: Fix unbalanced PHY init on probe errors mm, compaction: fast_find_migrateblock() should return pfn in the target zone dlm: fix plock invalid read dlm: fix missing lkb refcount handling ocfs2: dlmfs: fix error handling of user_dlm_destroy_lock scsi: dc395x: Fix a missing check on list iterator scsi: ufs: qcom: Add a readl() to make sure ref_clk gets enabled drm/amdgpu/cs: make commands with 0 chunks illegal behaviour. drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem drm/nouveau/clk: Fix an incorrect NULL check on list iterator drm/bridge: analogix_dp: Grab runtime PM reference for DP-AUX md: fix an incorrect NULL check in does_sb_need_changing md: fix an incorrect NULL check in md_reload_sb mtd: cfi_cmdset_0002: Move and rename chip_check/chip_ready/chip_good_for_write media: coda: Fix reported H264 profile media: coda: Add more H264 levels for CODA960 Kconfig: Add option for asm goto w/ tied outputs to workaround clang-13 bug RDMA/hfi1: Fix potential integer multiplication overflow errors irqchip/armada-370-xp: Do not touch Performance Counter Overflow on A375, A38x, A39x irqchip: irq-xtensa-mx: fix initial IRQ affinity mac80211: upgrade passive scan to active scan on DFS channels after beacon rx um: chan_user: Fix winch_tramp() return value um: Fix out-of-bounds read in LDT setup iommu/msm: Fix an incorrect NULL check on list iterator nodemask.h: fix compilation error with GCC12 hugetlb: fix huge_pmd_unshare address update rtl818x: Prevent using not initialized queues ASoC: rt5514: Fix event generation for "DSP Voice Wake Up" control carl9170: tx: fix an incorrect use of list iterator serial: pch: don't overwrite xmit->buf[0] by x_char tilcdc: tilcdc_external: fix an incorrect NULL check on list iterator gma500: fix an incorrect NULL check on list iterator arm64: dts: qcom: ipq8074: fix the sleep clock frequency phy: qcom-qmp: fix struct clk leak on probe errors ARM: pxa: maybe fix gpio lookup tables docs/conf.py: Cope with removal of language=None in Sphinx 5.0.0 dt-bindings: gpio: altera: correct interrupt-cells blk-iolatency: Fix inflight count imbalances and IO hangs on offline phy: qcom-qmp: fix reset-controller leak on probe errors Kconfig: add config option for asm goto w/ outputs RDMA/rxe: Generate a completion for unsupported/invalid opcode MIPS: IP27: Remove incorrect `cpu_has_fpu' override bfq: Avoid merging queues with different parents bfq: Drop pointless unlock-lock pair bfq: Remove pointless bfq_init_rq() calls bfq: Get rid of __bio_blkcg() usage bfq: Make sure bfqg for which we are queueing requests is online block: fix bio_clone_blkg_association() to associate with proper blkcg_gq md: bcache: check the return value of kzalloc() in detached_dev_do_request() pcmcia: db1xxx_ss: restrict to MIPS_DB1XXX boards staging: greybus: codecs: fix type confusion of list iterator variable iio: adc: ad7124: Remove shift from scan_type tty: goldfish: Use tty_port_destroy() to destroy port tty: serial: owl: Fix missing clk_disable_unprepare() in owl_uart_probe tty: serial: fsl_lpuart: fix potential bug when using both of_alias_get_id and ida_simple_get usb: usbip: fix a refcount leak in stub_probe() usb: usbip: add missing device lock on tweak configuration cmd USB: storage: karma: fix rio_karma_init return usb: musb: Fix missing of_node_put() in omap2430_probe staging: fieldbus: Fix the error handling path in anybuss_host_common_probe() pwm: lp3943: Fix duty calculation in case period was clamped rpmsg: qcom_smd: Fix irq_of_parse_and_map() return value usb: dwc3: pci: Fix pm_runtime_get_sync() error checking firmware: stratix10-svc: fix a missing check on list iterator iio: adc: stmpe-adc: Fix wait_for_completion_timeout return value check iio: adc: sc27xx: fix read big scale voltage not right iio: adc: sc27xx: Fine tune the scale calibration values rpmsg: qcom_smd: Fix returning 0 if irq_of_parse_and_map() fails phy: qcom-qmp: fix pipe-clock imbalance on power-on failure serial: sifive: Report actual baud base rather than fixed 115200 coresight: cpu-debug: Replace mutex with mutex_trylock on panic notifier soc: rockchip: Fix refcount leak in rockchip_grf_init clocksource/drivers/riscv: Events are stopped during CPU suspend rtc: mt6397: check return value after calling platform_get_resource() serial: meson: acquire port->lock in startup() serial: 8250_fintek: Check SER_RS485_RTS_* only with RS485 serial: digicolor-usart: Don't allow CS5-6 serial: rda-uart: Don't allow CS5-6 serial: txx9: Don't allow CS5-6 serial: sh-sci: Don't allow CS5-6 serial: sifive: Sanitize CSIZE and c_iflag serial: st-asc: Sanitize CSIZE and correct PARENB for CS7 serial: stm32-usart: Correct CSIZE, bits, and parity firmware: dmi-sysfs: Fix memory leak in dmi_sysfs_register_handle bus: ti-sysc: Fix warnings for unbind for serial driver: base: fix UAF when driver_attach failed driver core: fix deadlock in __device_attach watchdog: ts4800_wdt: Fix refcount leak in ts4800_wdt_probe ASoC: fsl_sai: Fix FSL_SAI_xDR/xFR definition clocksource/drivers/oxnas-rps: Fix irq_of_parse_and_map() return value s390/crypto: fix scatterwalk_unmap() callers in AES-GCM net: sched: fixed barrier to prevent skbuff sticking in qdisc backlog net: ethernet: mtk_eth_soc: out of bounds read in mtk_hwlro_get_fdir_entry() net: dsa: mv88e6xxx: Fix refcount leak in mv88e6xxx_mdios_register modpost: fix removing numeric suffixes jffs2: fix memory leak in jffs2_do_fill_super ubi: ubi_create_volume: Fix use-after-free when volume creation failed nfp: only report pause frame configuration for physical device net/mlx5: Don't use already freed action pointer net/mlx5e: Update netdev features after changing XDP state net: sched: add barrier to fix packet stuck problem for lockless qdisc tcp: tcp_rtx_synack() can be called from process context afs: Fix infinite loop found by xfstest generic/676 tipc: check attribute length for bearer name perf c2c: Fix sorting in percent_rmt_hitm_cmp() mips: cpc: Fix refcount leak in mips_cpc_default_phys_base tracing: Fix sleeping function called from invalid context on RT kernel tracing: Avoid adding tracer option before update_tracer_options f2fs: remove WARN_ON in f2fs_is_valid_blkaddr i2c: cadence: Increase timeout per message if necessary m68knommu: set ZERO_PAGE() to the allocated zeroed page m68knommu: fix undefined reference to `_init_sp' dmaengine: zynqmp_dma: In struct zynqmp_dma_chan fix desc_size data type NFSv4: Don't hold the layoutget locks across multiple RPC calls video: fbdev: pxa3xx-gcu: release the resources correctly in pxa3xx_gcu_probe/remove() xprtrdma: treat all calls not a bcall when bc_serv is NULL netfilter: nat: really support inet nat without l3 address ata: pata_octeon_cf: Fix refcount leak in octeon_cf_probe netfilter: nf_tables: memleak flow rule from commit path xen: unexport __init-annotated xen_xlate_map_ballooned_pages() af_unix: Fix a data-race in unix_dgram_peer_wake_me(). bpf, arm64: Clear prog->jited_len along prog->jited net: dsa: lantiq_gswip: Fix refcount leak in gswip_gphy_fw_list net/mlx4_en: Fix wrong return value on ioctl EEPROM query failure SUNRPC: Fix the calculation of xdr->end in xdr_get_next_encode_buffer() net: mdio: unexport __init-annotated mdio_bus_init() net: xfrm: unexport __init-annotated xfrm4_protocol_init() net: ipv6: unexport __init-annotated seg6_hmac_init() net/mlx5: Rearm the FW tracer after each tracer event net/mlx5: fs, fail conflicting actions ip_gre: test csum_start instead of transport header net: altera: Fix refcount leak in altera_tse_mdio_create drm: imx: fix compiler warning with gcc-12 iio: dummy: iio_simple_dummy: check the return value of kstrdup() iio: st_sensors: Add a local lock for protecting odr lkdtm/usercopy: Expand size of "out of frame" object tty: synclink_gt: Fix null-pointer-dereference in slgt_clean() tty: Fix a possible resource leak in icom_probe drivers: staging: rtl8192u: Fix deadlock in ieee80211_beacons_stop() drivers: staging: rtl8192e: Fix deadlock in rtllib_beacons_stop() USB: host: isp116x: check return value after calling platform_get_resource() drivers: tty: serial: Fix deadlock in sa1100_set_termios() drivers: usb: host: Fix deadlock in oxu_bus_suspend() USB: hcd-pci: Fully suspend across freeze/thaw cycle usb: dwc2: gadget: don't reset gadget's driver->bus misc: rtsx: set NULL intfdata when probe fails extcon: Modify extcon device to be created after driver data is set clocksource/drivers/sp804: Avoid error on multiple instances staging: rtl8712: fix uninit-value in usb_read8() and friends staging: rtl8712: fix uninit-value in r871xu_drv_init() serial: msm_serial: disable interrupts in __msm_console_write() kernfs: Separate kernfs_pr_cont_buf and rename_lock. watchdog: wdat_wdt: Stop watchdog when rebooting the system md: protect md_unregister_thread from reentrancy scsi: myrb: Fix up null pointer access on myrb_cleanup() Revert "net: af_key: add check for pfkey_broadcast in function pfkey_process" ceph: allow ceph.dir.rctime xattr to be updatable drm/radeon: fix a possible null pointer dereference modpost: fix undefined behavior of is_arm_mapping_symbol() x86/cpu: Elide KCSAN for cpu_has() and friends nbd: call genl_unregister_family() first in nbd_cleanup() nbd: fix race between nbd_alloc_config() and module removal nbd: fix io hung while disconnecting device s390/gmap: voluntarily schedule during key setting cifs: version operations for smb20 unneeded when legacy support disabled nodemask: Fix return values to be unsigned vringh: Fix loop descriptors check in the indirect cases scripts/gdb: change kernel config dumping method ALSA: hda/conexant - Fix loopback issue with CX20632 cifs: return errors during session setup during reconnects ata: libata-transport: fix {dma|pio|xfer}_mode sysfs files mmc: block: Fix CQE recovery reset success nfc: st21nfca: fix incorrect validating logic in EVT_TRANSACTION nfc: st21nfca: fix memory leaks in EVT_TRANSACTION handling ixgbe: fix bcast packets Rx on VF after promisc removal ixgbe: fix unexpected VLAN Rx in promisc mode on VF Input: bcm5974 - set missing URB_NO_TRANSFER_DMA_MAP urb flag powerpc/32: Fix overread/overwrite of thread_struct via ptrace md/raid0: Ignore RAID0 layout if the second zone has only one device mtd: cfi_cmdset_0002: Use chip_ready() for write on S29GL064N tcp: fix tcp_mtup_probe_success vs wrong snd_cwnd Linux 5.4.198 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I05615e33dbd0029f93c9724c9abc9cb9035122d2
879 lines
26 KiB
C
879 lines
26 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* fs/f2fs/segment.h
|
|
*
|
|
* Copyright (c) 2012 Samsung Electronics Co., Ltd.
|
|
* http://www.samsung.com/
|
|
*/
|
|
#include <linux/blkdev.h>
|
|
#include <linux/backing-dev.h>
|
|
|
|
/* constant macro */
|
|
#define NULL_SEGNO ((unsigned int)(~0))
|
|
#define NULL_SECNO ((unsigned int)(~0))
|
|
|
|
#define DEF_RECLAIM_PREFREE_SEGMENTS 5 /* 5% over total segments */
|
|
#define DEF_MAX_RECLAIM_PREFREE_SEGMENTS 4096 /* 8GB in maximum */
|
|
|
|
#define F2FS_MIN_SEGMENTS 9 /* SB + 2 (CP + SIT + NAT) + SSA + MAIN */
|
|
#define F2FS_MIN_META_SEGMENTS 8 /* SB + 2 (CP + SIT + NAT) + SSA */
|
|
|
|
/* L: Logical segment # in volume, R: Relative segment # in main area */
|
|
#define GET_L2R_SEGNO(free_i, segno) ((segno) - (free_i)->start_segno)
|
|
#define GET_R2L_SEGNO(free_i, segno) ((segno) + (free_i)->start_segno)
|
|
|
|
#define IS_DATASEG(t) ((t) <= CURSEG_COLD_DATA)
|
|
#define IS_NODESEG(t) ((t) >= CURSEG_HOT_NODE)
|
|
|
|
#define IS_HOT(t) ((t) == CURSEG_HOT_NODE || (t) == CURSEG_HOT_DATA)
|
|
#define IS_WARM(t) ((t) == CURSEG_WARM_NODE || (t) == CURSEG_WARM_DATA)
|
|
#define IS_COLD(t) ((t) == CURSEG_COLD_NODE || (t) == CURSEG_COLD_DATA)
|
|
|
|
#define IS_CURSEG(sbi, seg) \
|
|
(((seg) == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) || \
|
|
((seg) == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) || \
|
|
((seg) == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno) || \
|
|
((seg) == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno) || \
|
|
((seg) == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno) || \
|
|
((seg) == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno))
|
|
|
|
#define IS_CURSEC(sbi, secno) \
|
|
(((secno) == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno / \
|
|
(sbi)->segs_per_sec) || \
|
|
((secno) == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno / \
|
|
(sbi)->segs_per_sec) || \
|
|
((secno) == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno / \
|
|
(sbi)->segs_per_sec) || \
|
|
((secno) == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno / \
|
|
(sbi)->segs_per_sec) || \
|
|
((secno) == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno / \
|
|
(sbi)->segs_per_sec) || \
|
|
((secno) == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno / \
|
|
(sbi)->segs_per_sec)) \
|
|
|
|
#define MAIN_BLKADDR(sbi) \
|
|
(SM_I(sbi) ? SM_I(sbi)->main_blkaddr : \
|
|
le32_to_cpu(F2FS_RAW_SUPER(sbi)->main_blkaddr))
|
|
#define SEG0_BLKADDR(sbi) \
|
|
(SM_I(sbi) ? SM_I(sbi)->seg0_blkaddr : \
|
|
le32_to_cpu(F2FS_RAW_SUPER(sbi)->segment0_blkaddr))
|
|
|
|
#define MAIN_SEGS(sbi) (SM_I(sbi)->main_segments)
|
|
#define MAIN_SECS(sbi) ((sbi)->total_sections)
|
|
|
|
#define TOTAL_SEGS(sbi) \
|
|
(SM_I(sbi) ? SM_I(sbi)->segment_count : \
|
|
le32_to_cpu(F2FS_RAW_SUPER(sbi)->segment_count))
|
|
#define TOTAL_BLKS(sbi) (TOTAL_SEGS(sbi) << (sbi)->log_blocks_per_seg)
|
|
|
|
#define MAX_BLKADDR(sbi) (SEG0_BLKADDR(sbi) + TOTAL_BLKS(sbi))
|
|
#define SEGMENT_SIZE(sbi) (1ULL << ((sbi)->log_blocksize + \
|
|
(sbi)->log_blocks_per_seg))
|
|
|
|
#define START_BLOCK(sbi, segno) (SEG0_BLKADDR(sbi) + \
|
|
(GET_R2L_SEGNO(FREE_I(sbi), segno) << (sbi)->log_blocks_per_seg))
|
|
|
|
#define NEXT_FREE_BLKADDR(sbi, curseg) \
|
|
(START_BLOCK(sbi, (curseg)->segno) + (curseg)->next_blkoff)
|
|
|
|
#define GET_SEGOFF_FROM_SEG0(sbi, blk_addr) ((blk_addr) - SEG0_BLKADDR(sbi))
|
|
#define GET_SEGNO_FROM_SEG0(sbi, blk_addr) \
|
|
(GET_SEGOFF_FROM_SEG0(sbi, blk_addr) >> (sbi)->log_blocks_per_seg)
|
|
#define GET_BLKOFF_FROM_SEG0(sbi, blk_addr) \
|
|
(GET_SEGOFF_FROM_SEG0(sbi, blk_addr) & ((sbi)->blocks_per_seg - 1))
|
|
|
|
#define GET_SEGNO(sbi, blk_addr) \
|
|
((!__is_valid_data_blkaddr(blk_addr)) ? \
|
|
NULL_SEGNO : GET_L2R_SEGNO(FREE_I(sbi), \
|
|
GET_SEGNO_FROM_SEG0(sbi, blk_addr)))
|
|
#define BLKS_PER_SEC(sbi) \
|
|
((sbi)->segs_per_sec * (sbi)->blocks_per_seg)
|
|
#define GET_SEC_FROM_SEG(sbi, segno) \
|
|
(((segno) == -1) ? -1: (segno) / (sbi)->segs_per_sec)
|
|
#define GET_SEG_FROM_SEC(sbi, secno) \
|
|
((secno) * (sbi)->segs_per_sec)
|
|
#define GET_ZONE_FROM_SEC(sbi, secno) \
|
|
(((secno) == -1) ? -1: (secno) / (sbi)->secs_per_zone)
|
|
#define GET_ZONE_FROM_SEG(sbi, segno) \
|
|
GET_ZONE_FROM_SEC(sbi, GET_SEC_FROM_SEG(sbi, segno))
|
|
|
|
#define GET_SUM_BLOCK(sbi, segno) \
|
|
((sbi)->sm_info->ssa_blkaddr + (segno))
|
|
|
|
#define GET_SUM_TYPE(footer) ((footer)->entry_type)
|
|
#define SET_SUM_TYPE(footer, type) ((footer)->entry_type = (type))
|
|
|
|
#define SIT_ENTRY_OFFSET(sit_i, segno) \
|
|
((segno) % (sit_i)->sents_per_block)
|
|
#define SIT_BLOCK_OFFSET(segno) \
|
|
((segno) / SIT_ENTRY_PER_BLOCK)
|
|
#define START_SEGNO(segno) \
|
|
(SIT_BLOCK_OFFSET(segno) * SIT_ENTRY_PER_BLOCK)
|
|
#define SIT_BLK_CNT(sbi) \
|
|
DIV_ROUND_UP(MAIN_SEGS(sbi), SIT_ENTRY_PER_BLOCK)
|
|
#define f2fs_bitmap_size(nr) \
|
|
(BITS_TO_LONGS(nr) * sizeof(unsigned long))
|
|
|
|
#define SECTOR_FROM_BLOCK(blk_addr) \
|
|
(((sector_t)blk_addr) << F2FS_LOG_SECTORS_PER_BLOCK)
|
|
#define SECTOR_TO_BLOCK(sectors) \
|
|
((sectors) >> F2FS_LOG_SECTORS_PER_BLOCK)
|
|
|
|
/*
|
|
* indicate a block allocation direction: RIGHT and LEFT.
|
|
* RIGHT means allocating new sections towards the end of volume.
|
|
* LEFT means the opposite direction.
|
|
*/
|
|
enum {
|
|
ALLOC_RIGHT = 0,
|
|
ALLOC_LEFT
|
|
};
|
|
|
|
/*
|
|
* In the victim_sel_policy->alloc_mode, there are two block allocation modes.
|
|
* LFS writes data sequentially with cleaning operations.
|
|
* SSR (Slack Space Recycle) reuses obsolete space without cleaning operations.
|
|
*/
|
|
enum {
|
|
LFS = 0,
|
|
SSR
|
|
};
|
|
|
|
/*
|
|
* In the victim_sel_policy->gc_mode, there are two gc, aka cleaning, modes.
|
|
* GC_CB is based on cost-benefit algorithm.
|
|
* GC_GREEDY is based on greedy algorithm.
|
|
*/
|
|
enum {
|
|
GC_CB = 0,
|
|
GC_GREEDY,
|
|
ALLOC_NEXT,
|
|
FLUSH_DEVICE,
|
|
MAX_GC_POLICY,
|
|
};
|
|
|
|
/*
|
|
* BG_GC means the background cleaning job.
|
|
* FG_GC means the on-demand cleaning job.
|
|
* FORCE_FG_GC means on-demand cleaning job in background.
|
|
*/
|
|
enum {
|
|
BG_GC = 0,
|
|
FG_GC,
|
|
FORCE_FG_GC,
|
|
};
|
|
|
|
/* for a function parameter to select a victim segment */
|
|
struct victim_sel_policy {
|
|
int alloc_mode; /* LFS or SSR */
|
|
int gc_mode; /* GC_CB or GC_GREEDY */
|
|
unsigned long *dirty_segmap; /* dirty segment bitmap */
|
|
unsigned int max_search; /* maximum # of segments to search */
|
|
unsigned int offset; /* last scanned bitmap offset */
|
|
unsigned int ofs_unit; /* bitmap search unit */
|
|
unsigned int min_cost; /* minimum cost */
|
|
unsigned int min_segno; /* segment # having min. cost */
|
|
};
|
|
|
|
struct seg_entry {
|
|
unsigned int type:6; /* segment type like CURSEG_XXX_TYPE */
|
|
unsigned int valid_blocks:10; /* # of valid blocks */
|
|
unsigned int ckpt_valid_blocks:10; /* # of valid blocks last cp */
|
|
unsigned int padding:6; /* padding */
|
|
unsigned char *cur_valid_map; /* validity bitmap of blocks */
|
|
#ifdef CONFIG_F2FS_CHECK_FS
|
|
unsigned char *cur_valid_map_mir; /* mirror of current valid bitmap */
|
|
#endif
|
|
/*
|
|
* # of valid blocks and the validity bitmap stored in the the last
|
|
* checkpoint pack. This information is used by the SSR mode.
|
|
*/
|
|
unsigned char *ckpt_valid_map; /* validity bitmap of blocks last cp */
|
|
unsigned char *discard_map;
|
|
unsigned long long mtime; /* modification time of the segment */
|
|
};
|
|
|
|
struct sec_entry {
|
|
unsigned int valid_blocks; /* # of valid blocks in a section */
|
|
};
|
|
|
|
struct segment_allocation {
|
|
void (*allocate_segment)(struct f2fs_sb_info *, int, bool);
|
|
};
|
|
|
|
#define MAX_SKIP_GC_COUNT 16
|
|
|
|
struct inmem_pages {
|
|
struct list_head list;
|
|
struct page *page;
|
|
block_t old_addr; /* for revoking when fail to commit */
|
|
};
|
|
|
|
struct sit_info {
|
|
const struct segment_allocation *s_ops;
|
|
|
|
block_t sit_base_addr; /* start block address of SIT area */
|
|
block_t sit_blocks; /* # of blocks used by SIT area */
|
|
block_t written_valid_blocks; /* # of valid blocks in main area */
|
|
char *bitmap; /* all bitmaps pointer */
|
|
char *sit_bitmap; /* SIT bitmap pointer */
|
|
#ifdef CONFIG_F2FS_CHECK_FS
|
|
char *sit_bitmap_mir; /* SIT bitmap mirror */
|
|
|
|
/* bitmap of segments to be ignored by GC in case of errors */
|
|
unsigned long *invalid_segmap;
|
|
#endif
|
|
unsigned int bitmap_size; /* SIT bitmap size */
|
|
|
|
unsigned long *tmp_map; /* bitmap for temporal use */
|
|
unsigned long *dirty_sentries_bitmap; /* bitmap for dirty sentries */
|
|
unsigned int dirty_sentries; /* # of dirty sentries */
|
|
unsigned int sents_per_block; /* # of SIT entries per block */
|
|
struct rw_semaphore sentry_lock; /* to protect SIT cache */
|
|
struct seg_entry *sentries; /* SIT segment-level cache */
|
|
struct sec_entry *sec_entries; /* SIT section-level cache */
|
|
|
|
/* for cost-benefit algorithm in cleaning procedure */
|
|
unsigned long long elapsed_time; /* elapsed time after mount */
|
|
unsigned long long mounted_time; /* mount time */
|
|
unsigned long long min_mtime; /* min. modification time */
|
|
unsigned long long max_mtime; /* max. modification time */
|
|
|
|
unsigned int last_victim[MAX_GC_POLICY]; /* last victim segment # */
|
|
};
|
|
|
|
struct free_segmap_info {
|
|
unsigned int start_segno; /* start segment number logically */
|
|
unsigned int free_segments; /* # of free segments */
|
|
unsigned int free_sections; /* # of free sections */
|
|
spinlock_t segmap_lock; /* free segmap lock */
|
|
unsigned long *free_segmap; /* free segment bitmap */
|
|
unsigned long *free_secmap; /* free section bitmap */
|
|
};
|
|
|
|
/* Notice: The order of dirty type is same with CURSEG_XXX in f2fs.h */
|
|
enum dirty_type {
|
|
DIRTY_HOT_DATA, /* dirty segments assigned as hot data logs */
|
|
DIRTY_WARM_DATA, /* dirty segments assigned as warm data logs */
|
|
DIRTY_COLD_DATA, /* dirty segments assigned as cold data logs */
|
|
DIRTY_HOT_NODE, /* dirty segments assigned as hot node logs */
|
|
DIRTY_WARM_NODE, /* dirty segments assigned as warm node logs */
|
|
DIRTY_COLD_NODE, /* dirty segments assigned as cold node logs */
|
|
DIRTY, /* to count # of dirty segments */
|
|
PRE, /* to count # of entirely obsolete segments */
|
|
NR_DIRTY_TYPE
|
|
};
|
|
|
|
struct dirty_seglist_info {
|
|
const struct victim_selection *v_ops; /* victim selction operation */
|
|
unsigned long *dirty_segmap[NR_DIRTY_TYPE];
|
|
struct mutex seglist_lock; /* lock for segment bitmaps */
|
|
int nr_dirty[NR_DIRTY_TYPE]; /* # of dirty segments */
|
|
unsigned long *victim_secmap; /* background GC victims */
|
|
};
|
|
|
|
/* victim selection function for cleaning and SSR */
|
|
struct victim_selection {
|
|
int (*get_victim)(struct f2fs_sb_info *, unsigned int *,
|
|
int, int, char);
|
|
};
|
|
|
|
/* for active log information */
|
|
struct curseg_info {
|
|
struct mutex curseg_mutex; /* lock for consistency */
|
|
struct f2fs_summary_block *sum_blk; /* cached summary block */
|
|
struct rw_semaphore journal_rwsem; /* protect journal area */
|
|
struct f2fs_journal *journal; /* cached journal info */
|
|
unsigned char alloc_type; /* current allocation type */
|
|
unsigned int segno; /* current segment number */
|
|
unsigned short next_blkoff; /* next block offset to write */
|
|
unsigned int zone; /* current zone number */
|
|
unsigned int next_segno; /* preallocated segment */
|
|
};
|
|
|
|
struct sit_entry_set {
|
|
struct list_head set_list; /* link with all sit sets */
|
|
unsigned int start_segno; /* start segno of sits in set */
|
|
unsigned int entry_cnt; /* the # of sit entries in set */
|
|
};
|
|
|
|
/*
|
|
* inline functions
|
|
*/
|
|
static inline struct curseg_info *CURSEG_I(struct f2fs_sb_info *sbi, int type)
|
|
{
|
|
if (type == CURSEG_COLD_DATA_PINNED)
|
|
type = CURSEG_COLD_DATA;
|
|
return (struct curseg_info *)(SM_I(sbi)->curseg_array + type);
|
|
}
|
|
|
|
static inline struct seg_entry *get_seg_entry(struct f2fs_sb_info *sbi,
|
|
unsigned int segno)
|
|
{
|
|
struct sit_info *sit_i = SIT_I(sbi);
|
|
return &sit_i->sentries[segno];
|
|
}
|
|
|
|
static inline struct sec_entry *get_sec_entry(struct f2fs_sb_info *sbi,
|
|
unsigned int segno)
|
|
{
|
|
struct sit_info *sit_i = SIT_I(sbi);
|
|
return &sit_i->sec_entries[GET_SEC_FROM_SEG(sbi, segno)];
|
|
}
|
|
|
|
static inline unsigned int get_valid_blocks(struct f2fs_sb_info *sbi,
|
|
unsigned int segno, bool use_section)
|
|
{
|
|
/*
|
|
* In order to get # of valid blocks in a section instantly from many
|
|
* segments, f2fs manages two counting structures separately.
|
|
*/
|
|
if (use_section && __is_large_section(sbi))
|
|
return get_sec_entry(sbi, segno)->valid_blocks;
|
|
else
|
|
return get_seg_entry(sbi, segno)->valid_blocks;
|
|
}
|
|
|
|
static inline unsigned int get_ckpt_valid_blocks(struct f2fs_sb_info *sbi,
|
|
unsigned int segno)
|
|
{
|
|
return get_seg_entry(sbi, segno)->ckpt_valid_blocks;
|
|
}
|
|
|
|
static inline void seg_info_from_raw_sit(struct seg_entry *se,
|
|
struct f2fs_sit_entry *rs)
|
|
{
|
|
se->valid_blocks = GET_SIT_VBLOCKS(rs);
|
|
se->ckpt_valid_blocks = GET_SIT_VBLOCKS(rs);
|
|
memcpy(se->cur_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE);
|
|
memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE);
|
|
#ifdef CONFIG_F2FS_CHECK_FS
|
|
memcpy(se->cur_valid_map_mir, rs->valid_map, SIT_VBLOCK_MAP_SIZE);
|
|
#endif
|
|
se->type = GET_SIT_TYPE(rs);
|
|
se->mtime = le64_to_cpu(rs->mtime);
|
|
}
|
|
|
|
static inline void __seg_info_to_raw_sit(struct seg_entry *se,
|
|
struct f2fs_sit_entry *rs)
|
|
{
|
|
unsigned short raw_vblocks = (se->type << SIT_VBLOCKS_SHIFT) |
|
|
se->valid_blocks;
|
|
rs->vblocks = cpu_to_le16(raw_vblocks);
|
|
memcpy(rs->valid_map, se->cur_valid_map, SIT_VBLOCK_MAP_SIZE);
|
|
rs->mtime = cpu_to_le64(se->mtime);
|
|
}
|
|
|
|
static inline void seg_info_to_sit_page(struct f2fs_sb_info *sbi,
|
|
struct page *page, unsigned int start)
|
|
{
|
|
struct f2fs_sit_block *raw_sit;
|
|
struct seg_entry *se;
|
|
struct f2fs_sit_entry *rs;
|
|
unsigned int end = min(start + SIT_ENTRY_PER_BLOCK,
|
|
(unsigned long)MAIN_SEGS(sbi));
|
|
int i;
|
|
|
|
raw_sit = (struct f2fs_sit_block *)page_address(page);
|
|
memset(raw_sit, 0, PAGE_SIZE);
|
|
for (i = 0; i < end - start; i++) {
|
|
rs = &raw_sit->entries[i];
|
|
se = get_seg_entry(sbi, start + i);
|
|
__seg_info_to_raw_sit(se, rs);
|
|
}
|
|
}
|
|
|
|
static inline void seg_info_to_raw_sit(struct seg_entry *se,
|
|
struct f2fs_sit_entry *rs)
|
|
{
|
|
__seg_info_to_raw_sit(se, rs);
|
|
|
|
memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE);
|
|
se->ckpt_valid_blocks = se->valid_blocks;
|
|
}
|
|
|
|
static inline unsigned int find_next_inuse(struct free_segmap_info *free_i,
|
|
unsigned int max, unsigned int segno)
|
|
{
|
|
unsigned int ret;
|
|
spin_lock(&free_i->segmap_lock);
|
|
ret = find_next_bit(free_i->free_segmap, max, segno);
|
|
spin_unlock(&free_i->segmap_lock);
|
|
return ret;
|
|
}
|
|
|
|
static inline void __set_free(struct f2fs_sb_info *sbi, unsigned int segno)
|
|
{
|
|
struct free_segmap_info *free_i = FREE_I(sbi);
|
|
unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
|
|
unsigned int start_segno = GET_SEG_FROM_SEC(sbi, secno);
|
|
unsigned int next;
|
|
|
|
spin_lock(&free_i->segmap_lock);
|
|
clear_bit(segno, free_i->free_segmap);
|
|
free_i->free_segments++;
|
|
|
|
next = find_next_bit(free_i->free_segmap,
|
|
start_segno + sbi->segs_per_sec, start_segno);
|
|
if (next >= start_segno + sbi->segs_per_sec) {
|
|
clear_bit(secno, free_i->free_secmap);
|
|
free_i->free_sections++;
|
|
}
|
|
spin_unlock(&free_i->segmap_lock);
|
|
}
|
|
|
|
static inline void __set_inuse(struct f2fs_sb_info *sbi,
|
|
unsigned int segno)
|
|
{
|
|
struct free_segmap_info *free_i = FREE_I(sbi);
|
|
unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
|
|
|
|
set_bit(segno, free_i->free_segmap);
|
|
free_i->free_segments--;
|
|
if (!test_and_set_bit(secno, free_i->free_secmap))
|
|
free_i->free_sections--;
|
|
}
|
|
|
|
static inline void __set_test_and_free(struct f2fs_sb_info *sbi,
|
|
unsigned int segno)
|
|
{
|
|
struct free_segmap_info *free_i = FREE_I(sbi);
|
|
unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
|
|
unsigned int start_segno = GET_SEG_FROM_SEC(sbi, secno);
|
|
unsigned int next;
|
|
|
|
spin_lock(&free_i->segmap_lock);
|
|
if (test_and_clear_bit(segno, free_i->free_segmap)) {
|
|
free_i->free_segments++;
|
|
|
|
if (IS_CURSEC(sbi, secno))
|
|
goto skip_free;
|
|
next = find_next_bit(free_i->free_segmap,
|
|
start_segno + sbi->segs_per_sec, start_segno);
|
|
if (next >= start_segno + sbi->segs_per_sec) {
|
|
if (test_and_clear_bit(secno, free_i->free_secmap))
|
|
free_i->free_sections++;
|
|
}
|
|
}
|
|
skip_free:
|
|
spin_unlock(&free_i->segmap_lock);
|
|
}
|
|
|
|
static inline void __set_test_and_inuse(struct f2fs_sb_info *sbi,
|
|
unsigned int segno)
|
|
{
|
|
struct free_segmap_info *free_i = FREE_I(sbi);
|
|
unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
|
|
|
|
spin_lock(&free_i->segmap_lock);
|
|
if (!test_and_set_bit(segno, free_i->free_segmap)) {
|
|
free_i->free_segments--;
|
|
if (!test_and_set_bit(secno, free_i->free_secmap))
|
|
free_i->free_sections--;
|
|
}
|
|
spin_unlock(&free_i->segmap_lock);
|
|
}
|
|
|
|
static inline void get_sit_bitmap(struct f2fs_sb_info *sbi,
|
|
void *dst_addr)
|
|
{
|
|
struct sit_info *sit_i = SIT_I(sbi);
|
|
|
|
#ifdef CONFIG_F2FS_CHECK_FS
|
|
if (memcmp(sit_i->sit_bitmap, sit_i->sit_bitmap_mir,
|
|
sit_i->bitmap_size))
|
|
f2fs_bug_on(sbi, 1);
|
|
#endif
|
|
memcpy(dst_addr, sit_i->sit_bitmap, sit_i->bitmap_size);
|
|
}
|
|
|
|
static inline block_t written_block_count(struct f2fs_sb_info *sbi)
|
|
{
|
|
return SIT_I(sbi)->written_valid_blocks;
|
|
}
|
|
|
|
static inline unsigned int free_segments(struct f2fs_sb_info *sbi)
|
|
{
|
|
return FREE_I(sbi)->free_segments;
|
|
}
|
|
|
|
static inline int reserved_segments(struct f2fs_sb_info *sbi)
|
|
{
|
|
return SM_I(sbi)->reserved_segments +
|
|
SM_I(sbi)->additional_reserved_segments;
|
|
}
|
|
|
|
static inline unsigned int free_sections(struct f2fs_sb_info *sbi)
|
|
{
|
|
return FREE_I(sbi)->free_sections;
|
|
}
|
|
|
|
static inline unsigned int prefree_segments(struct f2fs_sb_info *sbi)
|
|
{
|
|
return DIRTY_I(sbi)->nr_dirty[PRE];
|
|
}
|
|
|
|
static inline unsigned int dirty_segments(struct f2fs_sb_info *sbi)
|
|
{
|
|
return DIRTY_I(sbi)->nr_dirty[DIRTY_HOT_DATA] +
|
|
DIRTY_I(sbi)->nr_dirty[DIRTY_WARM_DATA] +
|
|
DIRTY_I(sbi)->nr_dirty[DIRTY_COLD_DATA] +
|
|
DIRTY_I(sbi)->nr_dirty[DIRTY_HOT_NODE] +
|
|
DIRTY_I(sbi)->nr_dirty[DIRTY_WARM_NODE] +
|
|
DIRTY_I(sbi)->nr_dirty[DIRTY_COLD_NODE];
|
|
}
|
|
|
|
static inline int overprovision_segments(struct f2fs_sb_info *sbi)
|
|
{
|
|
return SM_I(sbi)->ovp_segments;
|
|
}
|
|
|
|
static inline int reserved_sections(struct f2fs_sb_info *sbi)
|
|
{
|
|
return GET_SEC_FROM_SEG(sbi, (unsigned int)reserved_segments(sbi));
|
|
}
|
|
|
|
static inline bool has_curseg_enough_space(struct f2fs_sb_info *sbi,
|
|
unsigned int node_blocks, unsigned int dent_blocks)
|
|
{
|
|
|
|
unsigned int segno, left_blocks;
|
|
int i;
|
|
|
|
/* check current node segment */
|
|
for (i = CURSEG_HOT_NODE; i <= CURSEG_COLD_NODE; i++) {
|
|
segno = CURSEG_I(sbi, i)->segno;
|
|
left_blocks = sbi->blocks_per_seg -
|
|
get_seg_entry(sbi, segno)->ckpt_valid_blocks;
|
|
|
|
if (node_blocks > left_blocks)
|
|
return false;
|
|
}
|
|
|
|
/* check current data segment */
|
|
segno = CURSEG_I(sbi, CURSEG_HOT_DATA)->segno;
|
|
left_blocks = sbi->blocks_per_seg -
|
|
get_seg_entry(sbi, segno)->ckpt_valid_blocks;
|
|
if (dent_blocks > left_blocks)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi,
|
|
int freed, int needed)
|
|
{
|
|
unsigned int total_node_blocks = get_pages(sbi, F2FS_DIRTY_NODES) +
|
|
get_pages(sbi, F2FS_DIRTY_DENTS) +
|
|
get_pages(sbi, F2FS_DIRTY_IMETA);
|
|
unsigned int total_dent_blocks = get_pages(sbi, F2FS_DIRTY_DENTS);
|
|
unsigned int node_secs = total_node_blocks / BLKS_PER_SEC(sbi);
|
|
unsigned int dent_secs = total_dent_blocks / BLKS_PER_SEC(sbi);
|
|
unsigned int node_blocks = total_node_blocks % BLKS_PER_SEC(sbi);
|
|
unsigned int dent_blocks = total_dent_blocks % BLKS_PER_SEC(sbi);
|
|
unsigned int free, need_lower, need_upper;
|
|
|
|
if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
|
|
return false;
|
|
|
|
free = free_sections(sbi) + freed;
|
|
need_lower = node_secs + dent_secs + reserved_sections(sbi) + needed;
|
|
need_upper = need_lower + (node_blocks ? 1 : 0) + (dent_blocks ? 1 : 0);
|
|
|
|
if (free > need_upper)
|
|
return false;
|
|
else if (free <= need_lower)
|
|
return true;
|
|
return !has_curseg_enough_space(sbi, node_blocks, dent_blocks);
|
|
}
|
|
|
|
static inline bool f2fs_is_checkpoint_ready(struct f2fs_sb_info *sbi)
|
|
{
|
|
if (likely(!is_sbi_flag_set(sbi, SBI_CP_DISABLED)))
|
|
return true;
|
|
if (likely(!has_not_enough_free_secs(sbi, 0, 0)))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
static inline bool excess_prefree_segs(struct f2fs_sb_info *sbi)
|
|
{
|
|
return prefree_segments(sbi) > SM_I(sbi)->rec_prefree_segments;
|
|
}
|
|
|
|
static inline int utilization(struct f2fs_sb_info *sbi)
|
|
{
|
|
return div_u64((u64)valid_user_blocks(sbi) * 100,
|
|
sbi->user_block_count);
|
|
}
|
|
|
|
/*
|
|
* Sometimes f2fs may be better to drop out-of-place update policy.
|
|
* And, users can control the policy through sysfs entries.
|
|
* There are five policies with triggering conditions as follows.
|
|
* F2FS_IPU_FORCE - all the time,
|
|
* F2FS_IPU_SSR - if SSR mode is activated,
|
|
* F2FS_IPU_UTIL - if FS utilization is over threashold,
|
|
* F2FS_IPU_SSR_UTIL - if SSR mode is activated and FS utilization is over
|
|
* threashold,
|
|
* F2FS_IPU_FSYNC - activated in fsync path only for high performance flash
|
|
* storages. IPU will be triggered only if the # of dirty
|
|
* pages over min_fsync_blocks. (=default option)
|
|
* F2FS_IPU_ASYNC - do IPU given by asynchronous write requests.
|
|
* F2FS_IPU_NOCACHE - disable IPU bio cache.
|
|
* F2FS_IPUT_DISABLE - disable IPU. (=default option in LFS mode)
|
|
*/
|
|
#define DEF_MIN_IPU_UTIL 70
|
|
#define DEF_MIN_FSYNC_BLOCKS 8
|
|
#define DEF_MIN_HOT_BLOCKS 16
|
|
|
|
#define SMALL_VOLUME_SEGMENTS (16 * 512) /* 16GB */
|
|
|
|
enum {
|
|
F2FS_IPU_FORCE,
|
|
F2FS_IPU_SSR,
|
|
F2FS_IPU_UTIL,
|
|
F2FS_IPU_SSR_UTIL,
|
|
F2FS_IPU_FSYNC,
|
|
F2FS_IPU_ASYNC,
|
|
F2FS_IPU_NOCACHE,
|
|
};
|
|
|
|
static inline unsigned int curseg_segno(struct f2fs_sb_info *sbi,
|
|
int type)
|
|
{
|
|
struct curseg_info *curseg = CURSEG_I(sbi, type);
|
|
return curseg->segno;
|
|
}
|
|
|
|
static inline unsigned char curseg_alloc_type(struct f2fs_sb_info *sbi,
|
|
int type)
|
|
{
|
|
struct curseg_info *curseg = CURSEG_I(sbi, type);
|
|
return curseg->alloc_type;
|
|
}
|
|
|
|
static inline unsigned short curseg_blkoff(struct f2fs_sb_info *sbi, int type)
|
|
{
|
|
struct curseg_info *curseg = CURSEG_I(sbi, type);
|
|
return curseg->next_blkoff;
|
|
}
|
|
|
|
static inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno)
|
|
{
|
|
f2fs_bug_on(sbi, segno > TOTAL_SEGS(sbi) - 1);
|
|
}
|
|
|
|
static inline void verify_fio_blkaddr(struct f2fs_io_info *fio)
|
|
{
|
|
struct f2fs_sb_info *sbi = fio->sbi;
|
|
|
|
if (__is_valid_data_blkaddr(fio->old_blkaddr))
|
|
verify_blkaddr(sbi, fio->old_blkaddr, __is_meta_io(fio) ?
|
|
META_GENERIC : DATA_GENERIC);
|
|
verify_blkaddr(sbi, fio->new_blkaddr, __is_meta_io(fio) ?
|
|
META_GENERIC : DATA_GENERIC_ENHANCE);
|
|
}
|
|
|
|
/*
|
|
* Summary block is always treated as an invalid block
|
|
*/
|
|
static inline int check_block_count(struct f2fs_sb_info *sbi,
|
|
int segno, struct f2fs_sit_entry *raw_sit)
|
|
{
|
|
bool is_valid = test_bit_le(0, raw_sit->valid_map) ? true : false;
|
|
int valid_blocks = 0;
|
|
int cur_pos = 0, next_pos;
|
|
|
|
/* check bitmap with valid block count */
|
|
do {
|
|
if (is_valid) {
|
|
next_pos = find_next_zero_bit_le(&raw_sit->valid_map,
|
|
sbi->blocks_per_seg,
|
|
cur_pos);
|
|
valid_blocks += next_pos - cur_pos;
|
|
} else
|
|
next_pos = find_next_bit_le(&raw_sit->valid_map,
|
|
sbi->blocks_per_seg,
|
|
cur_pos);
|
|
cur_pos = next_pos;
|
|
is_valid = !is_valid;
|
|
} while (cur_pos < sbi->blocks_per_seg);
|
|
|
|
if (unlikely(GET_SIT_VBLOCKS(raw_sit) != valid_blocks)) {
|
|
f2fs_err(sbi, "Mismatch valid blocks %d vs. %d",
|
|
GET_SIT_VBLOCKS(raw_sit), valid_blocks);
|
|
set_sbi_flag(sbi, SBI_NEED_FSCK);
|
|
return -EFSCORRUPTED;
|
|
}
|
|
|
|
/* check segment usage, and check boundary of a given segment number */
|
|
if (unlikely(GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg
|
|
|| segno > TOTAL_SEGS(sbi) - 1)) {
|
|
f2fs_err(sbi, "Wrong valid blocks %d or segno %u",
|
|
GET_SIT_VBLOCKS(raw_sit), segno);
|
|
set_sbi_flag(sbi, SBI_NEED_FSCK);
|
|
return -EFSCORRUPTED;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi,
|
|
unsigned int start)
|
|
{
|
|
struct sit_info *sit_i = SIT_I(sbi);
|
|
unsigned int offset = SIT_BLOCK_OFFSET(start);
|
|
block_t blk_addr = sit_i->sit_base_addr + offset;
|
|
|
|
check_seg_range(sbi, start);
|
|
|
|
#ifdef CONFIG_F2FS_CHECK_FS
|
|
if (f2fs_test_bit(offset, sit_i->sit_bitmap) !=
|
|
f2fs_test_bit(offset, sit_i->sit_bitmap_mir))
|
|
f2fs_bug_on(sbi, 1);
|
|
#endif
|
|
|
|
/* calculate sit block address */
|
|
if (f2fs_test_bit(offset, sit_i->sit_bitmap))
|
|
blk_addr += sit_i->sit_blocks;
|
|
|
|
return blk_addr;
|
|
}
|
|
|
|
static inline pgoff_t next_sit_addr(struct f2fs_sb_info *sbi,
|
|
pgoff_t block_addr)
|
|
{
|
|
struct sit_info *sit_i = SIT_I(sbi);
|
|
block_addr -= sit_i->sit_base_addr;
|
|
if (block_addr < sit_i->sit_blocks)
|
|
block_addr += sit_i->sit_blocks;
|
|
else
|
|
block_addr -= sit_i->sit_blocks;
|
|
|
|
return block_addr + sit_i->sit_base_addr;
|
|
}
|
|
|
|
static inline void set_to_next_sit(struct sit_info *sit_i, unsigned int start)
|
|
{
|
|
unsigned int block_off = SIT_BLOCK_OFFSET(start);
|
|
|
|
f2fs_change_bit(block_off, sit_i->sit_bitmap);
|
|
#ifdef CONFIG_F2FS_CHECK_FS
|
|
f2fs_change_bit(block_off, sit_i->sit_bitmap_mir);
|
|
#endif
|
|
}
|
|
|
|
static inline unsigned long long get_mtime(struct f2fs_sb_info *sbi,
|
|
bool base_time)
|
|
{
|
|
struct sit_info *sit_i = SIT_I(sbi);
|
|
time64_t diff, now = ktime_get_boottime_seconds();
|
|
|
|
if (now >= sit_i->mounted_time)
|
|
return sit_i->elapsed_time + now - sit_i->mounted_time;
|
|
|
|
/* system time is set to the past */
|
|
if (!base_time) {
|
|
diff = sit_i->mounted_time - now;
|
|
if (sit_i->elapsed_time >= diff)
|
|
return sit_i->elapsed_time - diff;
|
|
return 0;
|
|
}
|
|
return sit_i->elapsed_time;
|
|
}
|
|
|
|
static inline void set_summary(struct f2fs_summary *sum, nid_t nid,
|
|
unsigned int ofs_in_node, unsigned char version)
|
|
{
|
|
sum->nid = cpu_to_le32(nid);
|
|
sum->ofs_in_node = cpu_to_le16(ofs_in_node);
|
|
sum->version = version;
|
|
}
|
|
|
|
static inline block_t start_sum_block(struct f2fs_sb_info *sbi)
|
|
{
|
|
return __start_cp_addr(sbi) +
|
|
le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum);
|
|
}
|
|
|
|
static inline block_t sum_blk_addr(struct f2fs_sb_info *sbi, int base, int type)
|
|
{
|
|
return __start_cp_addr(sbi) +
|
|
le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_total_block_count)
|
|
- (base + 1) + type;
|
|
}
|
|
|
|
static inline bool sec_usage_check(struct f2fs_sb_info *sbi, unsigned int secno)
|
|
{
|
|
if (IS_CURSEC(sbi, secno) || (sbi->cur_victim_sec == secno))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* It is very important to gather dirty pages and write at once, so that we can
|
|
* submit a big bio without interfering other data writes.
|
|
* By default, 512 pages for directory data,
|
|
* 512 pages (2MB) * 8 for nodes, and
|
|
* 256 pages * 8 for meta are set.
|
|
*/
|
|
static inline int nr_pages_to_skip(struct f2fs_sb_info *sbi, int type)
|
|
{
|
|
if (sbi->sb->s_bdi->wb.dirty_exceeded)
|
|
return 0;
|
|
|
|
if (type == DATA)
|
|
return sbi->blocks_per_seg;
|
|
else if (type == NODE)
|
|
return 8 * sbi->blocks_per_seg;
|
|
else if (type == META)
|
|
return 8 * BIO_MAX_PAGES;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* When writing pages, it'd better align nr_to_write for segment size.
|
|
*/
|
|
static inline long nr_pages_to_write(struct f2fs_sb_info *sbi, int type,
|
|
struct writeback_control *wbc)
|
|
{
|
|
long nr_to_write, desired;
|
|
|
|
if (wbc->sync_mode != WB_SYNC_NONE)
|
|
return 0;
|
|
|
|
nr_to_write = wbc->nr_to_write;
|
|
desired = BIO_MAX_PAGES;
|
|
if (type == NODE)
|
|
desired <<= 1;
|
|
|
|
wbc->nr_to_write = desired;
|
|
return desired - nr_to_write;
|
|
}
|
|
|
|
static inline void wake_up_discard_thread(struct f2fs_sb_info *sbi, bool force)
|
|
{
|
|
struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
|
|
bool wakeup = false;
|
|
int i;
|
|
|
|
if (force)
|
|
goto wake_up;
|
|
|
|
mutex_lock(&dcc->cmd_lock);
|
|
for (i = MAX_PLIST_NUM - 1; i >= 0; i--) {
|
|
if (i + 1 < dcc->discard_granularity)
|
|
break;
|
|
if (!list_empty(&dcc->pend_list[i])) {
|
|
wakeup = true;
|
|
break;
|
|
}
|
|
}
|
|
mutex_unlock(&dcc->cmd_lock);
|
|
if (!wakeup || !is_idle(sbi, DISCARD_TIME))
|
|
return;
|
|
wake_up:
|
|
dcc->discard_wake = 1;
|
|
wake_up_interruptible_all(&dcc->discard_wait_queue);
|
|
}
|