Merge branch 'android12-5.10' into branch 'android12-5.10-lts'

Sync up with android12-5.10 for the following commits:

af699fd6a2 ANDROID: vendor_hook: skip trace_android_vh_page_trylock_set when ignore_references is true
5aec776ef8 BACKPORT: ANDROID: dma-buf: Move sysfs work out of DMA-BUF export path
d61d7ebf6f UPSTREAM: wifi: mac80211: fix MBSSID parsing use-after-free
173913b365 UPSTREAM: wifi: mac80211: don't parse mbssid in assoc response
9ed9ab8ca9 UPSTREAM: mac80211: mlme: find auth challenge directly
d6e68e31b8 UPSTREAM: wifi: cfg80211: update hidden BSSes to avoid WARN_ON
3ea906ba30 UPSTREAM: wifi: mac80211: fix crash in beacon protection for P2P-device
241426b24b UPSTREAM: wifi: mac80211_hwsim: avoid mac80211 warning on bad rate
50e27143a5 UPSTREAM: wifi: cfg80211: avoid nontransmitted BSS list corruption
05a0122295 UPSTREAM: wifi: cfg80211: fix BSS refcounting bugs
2e8c292e35 UPSTREAM: wifi: cfg80211: ensure length byte is present before access
5f6b14356a UPSTREAM: wifi: cfg80211/mac80211: reject bad MBSSID elements
6aeb3ccf09 UPSTREAM: wifi: cfg80211: fix u8 overflow in cfg80211_update_notlisted_nontrans()
13a84bfa4f ANDROID: GKI: Update symbols to symbol list
09f4246296 ANDROID: sched: add restricted hooks to replace the former hooks
376aaf803f ANDROID: GKI: Add symbol snd_pcm_stop_xrun
8512c353a2 ANDROID: ABI: update allowed list for galaxy
439fc06787 ANDROID: GKI: Update symbols to symbol list
beaaa7bff8 UPSTREAM: dma-buf: ensure unique directory name for dmabuf stats
d71115b1bf UPSTREAM: dma-buf: call dma_buf_stats_setup after dmabuf is in valid list
f9a66cbe70 ANDROID: GKI: Update symbol list for mtk AIoT projects
a3835ce695 UPSTREAM: psi: Fix psi state corruption when schedule() races with cgroup move
3b39e91301 BACKPORT: HID: steam: Prevent NULL pointer dereference in steam_{recv,send}_report
c35cda5280 BACKPORT: mm: don't be stuck to rmap lock on reclaim path
9613bc53b5 Revert "firmware_loader: use kernel credentials when reading firmware"
95f23ced41 UPSTREAM: crypto: jitter - add oversampling of noise source
b046e2dca5 ANDROID: Fix kenelci build-break for !CONFIG_PERF_EVENTS
24220df802 FROMGIT: f2fs: support recording stop_checkpoint reason into super_block
f18e68a234 UPSTREAM: wifi: mac80211_hwsim: use 32-bit skb cookie
08cb67eb33 UPSTREAM: wifi: mac80211_hwsim: add back erroneously removed cast
9b080edfbd UPSTREAM: wifi: mac80211_hwsim: fix race condition in pending packet

Update the .xml file with the newly tracked symbols:

Leaf changes summary: 30 artifacts changed
Changed leaf types summary: 0 leaf type changed
Removed/Changed/Added functions summary: 0 Removed, 0 Changed, 24 Added functions
Removed/Changed/Added variables summary: 0 Removed, 0 Changed, 6 Added variables

24 Added functions:

  [A] 'function void __rtnl_link_unregister(rtnl_link_ops*)'
  [A] 'function int __traceiter_android_rvh_alloc_si(void*, swap_info_struct**, bool*)'
  [A] 'function int __traceiter_android_rvh_alloc_swap_slot_cache(void*, swap_slots_cache*, int*, bool*)'
  [A] 'function int __traceiter_android_rvh_drain_slots_cache_cpu(void*, swap_slots_cache*, unsigned int, bool, bool*)'
  [A] 'function int __traceiter_android_rvh_free_swap_slot(void*, swp_entry_t, swap_slots_cache*, bool*)'
  [A] 'function int __traceiter_android_rvh_get_swap_page(void*, page*, swp_entry_t*, swap_slots_cache*, bool*)'
  [A] 'function int __traceiter_android_rvh_handle_pte_fault_end(void*, vm_fault*, unsigned long int)'
  [A] 'function net_device* dev_get_by_index_rcu(net*, int)'
  [A] 'function phy_device* fixed_phy_register(unsigned int, fixed_phy_status*, device_node*)'
  [A] 'function void fixed_phy_unregister(phy_device*)'
  [A] 'function irq_domain* irq_domain_add_simple(device_node*, unsigned int, unsigned int, const irq_domain_ops*, void*)'
  [A] 'function int nf_register_net_hook(net*, const nf_hook_ops*)'
  [A] 'function void nf_unregister_net_hook(net*, const nf_hook_ops*)'
  [A] 'function int phy_ethtool_set_wol(phy_device*, ethtool_wolinfo*)'
  [A] 'function int phy_register_fixup_for_uid(u32, u32, int (phy_device*)*)'
  [A] 'function int phy_save_page(phy_device*)'
  [A] 'function int phy_unregister_fixup_for_uid(u32, u32)'
  [A] 'function int snd_pcm_stop_xrun(snd_pcm_substream*)'
  [A] 'function void tty_encode_baud_rate(tty_struct*, speed_t, speed_t)'
  [A] 'function int usb_autopm_get_interface_async(usb_interface*)'
  [A] 'function void usb_autopm_put_interface_async(usb_interface*)'
  [A] 'function int usb_clear_halt(usb_device*, int)'
  [A] 'function int usb_interrupt_msg(usb_device*, unsigned int, void*, int, int*, int)'
  [A] 'function int usb_unlink_urb(urb*)'

6 Added variables:

  [A] 'tracepoint __tracepoint_android_rvh_alloc_si'
  [A] 'tracepoint __tracepoint_android_rvh_alloc_swap_slot_cache'
  [A] 'tracepoint __tracepoint_android_rvh_drain_slots_cache_cpu'
  [A] 'tracepoint __tracepoint_android_rvh_free_swap_slot'
  [A] 'tracepoint __tracepoint_android_rvh_get_swap_page'
  [A] 'tracepoint __tracepoint_android_rvh_handle_pte_fault_end'

Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: I225d5838de38d886151cf619654412ee8c5428b2
This commit is contained in:
Greg Kroah-Hartman
2022-10-27 07:20:00 +00:00
34 changed files with 1180 additions and 843 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1901,6 +1901,8 @@
find_vpid find_vpid
finish_wait finish_wait
firmware_request_nowarn firmware_request_nowarn
fixed_phy_register
fixed_phy_unregister
fixed_size_llseek fixed_size_llseek
flow_keys_basic_dissector flow_keys_basic_dissector
flush_dcache_page flush_dcache_page
@@ -2327,6 +2329,7 @@
irq_create_mapping_affinity irq_create_mapping_affinity
irq_create_of_mapping irq_create_of_mapping
irq_dispose_mapping irq_dispose_mapping
irq_domain_add_simple
irq_domain_alloc_irqs_parent irq_domain_alloc_irqs_parent
irq_domain_create_hierarchy irq_domain_create_hierarchy
irq_domain_free_irqs_common irq_domain_free_irqs_common
@@ -3023,6 +3026,7 @@
phy_ethtool_get_link_ksettings phy_ethtool_get_link_ksettings
phy_ethtool_nway_reset phy_ethtool_nway_reset
phy_ethtool_set_link_ksettings phy_ethtool_set_link_ksettings
phy_ethtool_set_wol
phy_exit phy_exit
phy_find_first phy_find_first
phy_get_pause phy_get_pause
@@ -3034,9 +3038,12 @@
phy_power_off phy_power_off
phy_power_on phy_power_on
phy_print_status phy_print_status
phy_register_fixup_for_uid
phy_save_page
phy_set_mode_ext phy_set_mode_ext
phy_start phy_start
phy_stop phy_stop
phy_unregister_fixup_for_uid
pick_highest_pushable_task pick_highest_pushable_task
pid_nr_ns pid_nr_ns
pid_task pid_task
@@ -4066,6 +4073,7 @@
ttm_tt_populate ttm_tt_populate
ttm_tt_set_placement_caching ttm_tt_set_placement_caching
ttm_unmap_and_unpopulate_pages ttm_unmap_and_unpopulate_pages
tty_encode_baud_rate
tty_flip_buffer_push tty_flip_buffer_push
tty_insert_flip_string_fixed_flag tty_insert_flip_string_fixed_flag
tty_kref_put tty_kref_put
@@ -4214,8 +4222,10 @@
usb_asmedia_modifyflowcontrol usb_asmedia_modifyflowcontrol
usb_assign_descriptors usb_assign_descriptors
usb_autopm_get_interface usb_autopm_get_interface
usb_autopm_get_interface_async
usb_autopm_get_interface_no_resume usb_autopm_get_interface_no_resume
usb_autopm_put_interface usb_autopm_put_interface
usb_autopm_put_interface_async
usb_bulk_msg usb_bulk_msg
usb_calc_bus_time usb_calc_bus_time
usb_choose_configuration usb_choose_configuration
@@ -4293,6 +4303,7 @@
usb_ifnum_to_if usb_ifnum_to_if
usb_initialize_gadget usb_initialize_gadget
usb_interface_id usb_interface_id
usb_interrupt_msg
usb_kill_urb usb_kill_urb
usb_match_id usb_match_id
usb_match_one_id usb_match_one_id

View File

@@ -3216,6 +3216,7 @@
update_devfreq update_devfreq
usb_add_phy_dev usb_add_phy_dev
usb_assign_descriptors usb_assign_descriptors
usb_clear_halt
usb_copy_descriptors usb_copy_descriptors
usb_ep_alloc_request usb_ep_alloc_request
usb_ep_autoconfig usb_ep_autoconfig
@@ -3239,6 +3240,7 @@
usb_phy_set_charger_current usb_phy_set_charger_current
usb_remove_phy usb_remove_phy
usb_role_switch_set_role usb_role_switch_set_role
usb_unlink_urb
v4l2_async_notifier_add_subdev v4l2_async_notifier_add_subdev
v4l2_async_notifier_cleanup v4l2_async_notifier_cleanup
v4l2_async_subdev_notifier_register v4l2_async_subdev_notifier_register

View File

@@ -408,6 +408,7 @@
dev_fwnode dev_fwnode
__dev_get_by_index __dev_get_by_index
dev_get_by_index dev_get_by_index
dev_get_by_index_rcu
dev_get_by_name dev_get_by_name
dev_get_regmap dev_get_regmap
dev_get_stats dev_get_stats
@@ -1658,7 +1659,9 @@
net_ratelimit net_ratelimit
nf_ct_attach nf_ct_attach
nf_ct_delete nf_ct_delete
nf_register_net_hook
nf_register_net_hooks nf_register_net_hooks
nf_unregister_net_hook
nf_unregister_net_hooks nf_unregister_net_hooks
nla_find nla_find
nla_memcpy nla_memcpy
@@ -2286,6 +2289,7 @@
rtc_update_irq rtc_update_irq
rtc_valid_tm rtc_valid_tm
rtnl_is_locked rtnl_is_locked
__rtnl_link_unregister
rtnl_lock rtnl_lock
rtnl_unlock rtnl_unlock
runqueues runqueues

View File

@@ -2626,6 +2626,7 @@
snd_pcm_fill_iec958_consumer snd_pcm_fill_iec958_consumer
snd_pcm_fill_iec958_consumer_hw_params snd_pcm_fill_iec958_consumer_hw_params
snd_pcm_hw_constraint_eld snd_pcm_hw_constraint_eld
snd_pcm_stop_xrun
# required by snd-soc-rk817.ko # required by snd-soc-rk817.ko
snd_soc_component_exit_regmap snd_soc_component_exit_regmap

View File

@@ -10,6 +10,7 @@
nr_swap_pages nr_swap_pages
plist_requeue plist_requeue
plist_del plist_del
__traceiter_android_rvh_handle_pte_fault_end
__traceiter_android_vh_handle_pte_fault_end __traceiter_android_vh_handle_pte_fault_end
__traceiter_android_vh_cow_user_page __traceiter_android_vh_cow_user_page
__traceiter_android_vh_swapin_add_anon_rmap __traceiter_android_vh_swapin_add_anon_rmap
@@ -20,9 +21,13 @@
__traceiter_android_vh_count_pswpout __traceiter_android_vh_count_pswpout
__traceiter_android_vh_count_swpout_vm_event __traceiter_android_vh_count_swpout_vm_event
__traceiter_android_vh_swap_slot_cache_active __traceiter_android_vh_swap_slot_cache_active
__traceiter_android_rvh_drain_slots_cache_cpu
__traceiter_android_vh_drain_slots_cache_cpu __traceiter_android_vh_drain_slots_cache_cpu
__traceiter_android_rvh_alloc_swap_slot_cache
__traceiter_android_vh_alloc_swap_slot_cache __traceiter_android_vh_alloc_swap_slot_cache
__traceiter_android_rvh_free_swap_slot
__traceiter_android_vh_free_swap_slot __traceiter_android_vh_free_swap_slot
__traceiter_android_rvh_get_swap_page
__traceiter_android_vh_get_swap_page __traceiter_android_vh_get_swap_page
__traceiter_android_vh_page_isolated_for_reclaim __traceiter_android_vh_page_isolated_for_reclaim
__traceiter_android_vh_inactive_is_low __traceiter_android_vh_inactive_is_low
@@ -31,10 +36,12 @@
__traceiter_android_vh_unuse_swap_page __traceiter_android_vh_unuse_swap_page
__traceiter_android_vh_init_swap_info_struct __traceiter_android_vh_init_swap_info_struct
__traceiter_android_vh_si_swapinfo __traceiter_android_vh_si_swapinfo
__traceiter_android_rvh_alloc_si
__traceiter_android_vh_alloc_si __traceiter_android_vh_alloc_si
__traceiter_android_vh_free_pages __traceiter_android_vh_free_pages
__traceiter_android_vh_set_shmem_page_flag __traceiter_android_vh_set_shmem_page_flag
__traceiter_android_vh_ra_tuning_max_page __traceiter_android_vh_ra_tuning_max_page
__tracepoint_android_rvh_handle_pte_fault_end
__tracepoint_android_vh_handle_pte_fault_end __tracepoint_android_vh_handle_pte_fault_end
__tracepoint_android_vh_cow_user_page __tracepoint_android_vh_cow_user_page
__tracepoint_android_vh_swapin_add_anon_rmap __tracepoint_android_vh_swapin_add_anon_rmap
@@ -45,9 +52,13 @@
__tracepoint_android_vh_count_pswpout __tracepoint_android_vh_count_pswpout
__tracepoint_android_vh_count_swpout_vm_event __tracepoint_android_vh_count_swpout_vm_event
__tracepoint_android_vh_swap_slot_cache_active __tracepoint_android_vh_swap_slot_cache_active
__tracepoint_android_rvh_drain_slots_cache_cpu
__tracepoint_android_vh_drain_slots_cache_cpu __tracepoint_android_vh_drain_slots_cache_cpu
__tracepoint_android_rvh_alloc_swap_slot_cache
__tracepoint_android_vh_alloc_swap_slot_cache __tracepoint_android_vh_alloc_swap_slot_cache
__tracepoint_android_rvh_free_swap_slot
__tracepoint_android_vh_free_swap_slot __tracepoint_android_vh_free_swap_slot
__tracepoint_android_rvh_get_swap_page
__tracepoint_android_vh_get_swap_page __tracepoint_android_vh_get_swap_page
__tracepoint_android_vh_page_isolated_for_reclaim __tracepoint_android_vh_page_isolated_for_reclaim
__tracepoint_android_vh_inactive_is_low __tracepoint_android_vh_inactive_is_low
@@ -56,6 +67,7 @@
__tracepoint_android_vh_unuse_swap_page __tracepoint_android_vh_unuse_swap_page
__tracepoint_android_vh_init_swap_info_struct __tracepoint_android_vh_init_swap_info_struct
__tracepoint_android_vh_si_swapinfo __tracepoint_android_vh_si_swapinfo
__tracepoint_android_rvh_alloc_si
__tracepoint_android_vh_alloc_si __tracepoint_android_vh_alloc_si
__tracepoint_android_vh_free_pages __tracepoint_android_vh_free_pages
__tracepoint_android_vh_set_shmem_page_flag __tracepoint_android_vh_set_shmem_page_flag

View File

@@ -117,6 +117,22 @@ struct rand_data {
#define JENT_EHEALTH 9 /* Health test failed during initialization */ #define JENT_EHEALTH 9 /* Health test failed during initialization */
#define JENT_ERCT 10 /* RCT failed during initialization */ #define JENT_ERCT 10 /* RCT failed during initialization */
/*
* The output n bits can receive more than n bits of min entropy, of course,
* but the fixed output of the conditioning function can only asymptotically
* approach the output size bits of min entropy, not attain that bound. Random
* maps will tend to have output collisions, which reduces the creditable
* output entropy (that is what SP 800-90B Section 3.1.5.1.2 attempts to bound).
*
* The value "64" is justified in Appendix A.4 of the current 90C draft,
* and aligns with NIST's in "epsilon" definition in this document, which is
* that a string can be considered "full entropy" if you can bound the min
* entropy in each bit of output to at least 1-epsilon, where epsilon is
* required to be <= 2^(-32).
*/
#define JENT_ENTROPY_SAFETY_FACTOR 64
#include <linux/fips.h>
#include "jitterentropy.h" #include "jitterentropy.h"
/*************************************************************************** /***************************************************************************
@@ -546,7 +562,10 @@ static int jent_measure_jitter(struct rand_data *ec)
*/ */
static void jent_gen_entropy(struct rand_data *ec) static void jent_gen_entropy(struct rand_data *ec)
{ {
unsigned int k = 0; unsigned int k = 0, safety_factor = 0;
if (fips_enabled)
safety_factor = JENT_ENTROPY_SAFETY_FACTOR;
/* priming of the ->prev_time value */ /* priming of the ->prev_time value */
jent_measure_jitter(ec); jent_measure_jitter(ec);
@@ -560,7 +579,7 @@ static void jent_gen_entropy(struct rand_data *ec)
* We multiply the loop value with ->osr to obtain the * We multiply the loop value with ->osr to obtain the
* oversampling rate requested by the caller * oversampling rate requested by the caller
*/ */
if (++k >= (DATA_SIZE_BITS * ec->osr)) if (++k >= ((DATA_SIZE_BITS + safety_factor) * ec->osr))
break; break;
} }
} }

View File

@@ -431,6 +431,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_binder_read_done);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_handle_tlb_conf); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_handle_tlb_conf);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_shrink_node_memcgs); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_shrink_node_memcgs);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_ra_tuning_max_page); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_ra_tuning_max_page);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_handle_pte_fault_end);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_handle_pte_fault_end); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_handle_pte_fault_end);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_cow_user_page); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_cow_user_page);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_swapin_add_anon_rmap); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_swapin_add_anon_rmap);
@@ -441,9 +442,13 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_count_pswpin);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_count_pswpout); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_count_pswpout);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_count_swpout_vm_event); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_count_swpout_vm_event);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_swap_slot_cache_active); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_swap_slot_cache_active);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_drain_slots_cache_cpu);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_drain_slots_cache_cpu); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_drain_slots_cache_cpu);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_alloc_swap_slot_cache);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alloc_swap_slot_cache); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alloc_swap_slot_cache);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_free_swap_slot);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_free_swap_slot); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_free_swap_slot);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_get_swap_page);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_get_swap_page); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_get_swap_page);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_madvise_cold_or_pageout); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_madvise_cold_or_pageout);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_page_isolated_for_reclaim); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_page_isolated_for_reclaim);
@@ -453,6 +458,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_account_swap_pages);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_unuse_swap_page); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_unuse_swap_page);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_init_swap_info_struct); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_init_swap_info_struct);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_si_swapinfo); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_si_swapinfo);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_alloc_si);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alloc_si); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_alloc_si);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_free_pages); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_free_pages);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_set_shmem_page_flag); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_set_shmem_page_flag);

View File

@@ -793,8 +793,6 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
size_t offset, u32 opt_flags) size_t offset, u32 opt_flags)
{ {
struct firmware *fw = NULL; struct firmware *fw = NULL;
struct cred *kern_cred = NULL;
const struct cred *old_cred;
bool nondirect = false; bool nondirect = false;
int ret; int ret;
@@ -811,18 +809,6 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
if (ret <= 0) /* error or already assigned */ if (ret <= 0) /* error or already assigned */
goto out; goto out;
/*
* We are about to try to access the firmware file. Because we may have been
* called by a driver when serving an unrelated request from userland, we use
* the kernel credentials to read the file.
*/
kern_cred = prepare_kernel_cred(NULL);
if (!kern_cred) {
ret = -ENOMEM;
goto out;
}
old_cred = override_creds(kern_cred);
ret = fw_get_filesystem_firmware(device, fw->priv, "", NULL); ret = fw_get_filesystem_firmware(device, fw->priv, "", NULL);
/* Only full reads can support decompression, platform, and sysfs. */ /* Only full reads can support decompression, platform, and sysfs. */
@@ -848,9 +834,6 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
} else } else
ret = assign_fw(fw, device); ret = assign_fw(fw, device);
revert_creds(old_cred);
put_cred(kern_cred);
out: out:
if (ret < 0) { if (ret < 0) {
fw_abort_batch_reqs(fw); fw_abort_batch_reqs(fw);

View File

@@ -11,6 +11,7 @@
#include <linux/printk.h> #include <linux/printk.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/sysfs.h> #include <linux/sysfs.h>
#include <linux/workqueue.h>
#include "dma-buf-sysfs-stats.h" #include "dma-buf-sysfs-stats.h"
@@ -135,10 +136,51 @@ void dma_buf_uninit_sysfs_statistics(void)
kset_unregister(dma_buf_stats_kset); kset_unregister(dma_buf_stats_kset);
} }
static void sysfs_add_workfn(struct work_struct *work)
{
/* The ABI would have to change for this to be false, but let's be paranoid. */
_Static_assert(sizeof(struct kobject) >= sizeof(struct work_struct),
"kobject is smaller than work_struct");
struct dma_buf_sysfs_entry *sysfs_entry =
container_of((struct kobject *)work, struct dma_buf_sysfs_entry, kobj);
struct dma_buf *dmabuf = sysfs_entry->dmabuf;
/*
* A dmabuf is ref-counted via its file member. If this handler holds the only
* reference to the dmabuf, there is no need for sysfs kobject creation. This is an
* optimization and a race; when the reference count drops to 1 immediately after
* this check it is not harmful as the sysfs entry will still get cleaned up in
* dma_buf_stats_teardown, which won't get called until the final dmabuf reference
* is released, and that can't happen until the end of this function.
*/
if (file_count(dmabuf->file) > 1) {
/*
* kobject_init_and_add expects kobject to be zero-filled, but we have populated it
* to trigger this work function.
*/
memset(&dmabuf->sysfs_entry->kobj, 0, sizeof(dmabuf->sysfs_entry->kobj));
dmabuf->sysfs_entry->kobj.kset = dma_buf_per_buffer_stats_kset;
if (kobject_init_and_add(&dmabuf->sysfs_entry->kobj, &dma_buf_ktype, NULL,
"%lu", file_inode(dmabuf->file)->i_ino)) {
kobject_put(&dmabuf->sysfs_entry->kobj);
dmabuf->sysfs_entry = NULL;
}
} else {
/*
* Free the sysfs_entry and reset the pointer so dma_buf_stats_teardown doesn't
* attempt to operate on it.
*/
kfree(dmabuf->sysfs_entry);
dmabuf->sysfs_entry = NULL;
}
dma_buf_put(dmabuf);
}
int dma_buf_stats_setup(struct dma_buf *dmabuf) int dma_buf_stats_setup(struct dma_buf *dmabuf)
{ {
struct dma_buf_sysfs_entry *sysfs_entry; struct dma_buf_sysfs_entry *sysfs_entry;
int ret; struct work_struct *work;
if (!dmabuf || !dmabuf->file) if (!dmabuf || !dmabuf->file)
return -EINVAL; return -EINVAL;
@@ -148,25 +190,21 @@ int dma_buf_stats_setup(struct dma_buf *dmabuf)
return -EINVAL; return -EINVAL;
} }
sysfs_entry = kzalloc(sizeof(struct dma_buf_sysfs_entry), GFP_KERNEL); sysfs_entry = kmalloc(sizeof(struct dma_buf_sysfs_entry), GFP_KERNEL);
if (!sysfs_entry) if (!sysfs_entry)
return -ENOMEM; return -ENOMEM;
sysfs_entry->kobj.kset = dma_buf_per_buffer_stats_kset;
sysfs_entry->dmabuf = dmabuf; sysfs_entry->dmabuf = dmabuf;
dmabuf->sysfs_entry = sysfs_entry; dmabuf->sysfs_entry = sysfs_entry;
/* create the directory for buffer stats */ /*
ret = kobject_init_and_add(&sysfs_entry->kobj, &dma_buf_ktype, NULL, * The use of kobj as a work_struct is an ugly hack
"%lu", file_inode(dmabuf->file)->i_ino); * to avoid an ABI break in this frozen kernel.
if (ret) */
goto err_sysfs_dmabuf; work = (struct work_struct *)&dmabuf->sysfs_entry->kobj;
INIT_WORK(work, sysfs_add_workfn);
get_dma_buf(dmabuf); /* This reference will be dropped in sysfs_add_workfn. */
schedule_work(work);
return 0; return 0;
err_sysfs_dmabuf:
kobject_put(&sysfs_entry->kobj);
dmabuf->sysfs_entry = NULL;
return ret;
} }

View File

@@ -486,6 +486,7 @@ EXPORT_SYMBOL_GPL(is_dma_buf_file);
static struct file *dma_buf_getfile(struct dma_buf *dmabuf, int flags) static struct file *dma_buf_getfile(struct dma_buf *dmabuf, int flags)
{ {
static atomic64_t dmabuf_inode = ATOMIC64_INIT(0);
struct file *file; struct file *file;
struct inode *inode = alloc_anon_inode(dma_buf_mnt->mnt_sb); struct inode *inode = alloc_anon_inode(dma_buf_mnt->mnt_sb);
@@ -495,6 +496,13 @@ static struct file *dma_buf_getfile(struct dma_buf *dmabuf, int flags)
inode->i_size = dmabuf->size; inode->i_size = dmabuf->size;
inode_set_bytes(inode, dmabuf->size); inode_set_bytes(inode, dmabuf->size);
/*
* The ->i_ino acquired from get_next_ino() is not unique thus
* not suitable for using it as dentry name by dmabuf stats.
* Override ->i_ino with the unique and dmabuffs specific
* value.
*/
inode->i_ino = atomic64_add_return(1, &dmabuf_inode);
file = alloc_file_pseudo(inode, dma_buf_mnt, "dmabuf", file = alloc_file_pseudo(inode, dma_buf_mnt, "dmabuf",
flags, &dma_buf_fops); flags, &dma_buf_fops);
if (IS_ERR(file)) if (IS_ERR(file))
@@ -621,10 +629,6 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
file->f_mode |= FMODE_LSEEK; file->f_mode |= FMODE_LSEEK;
dmabuf->file = file; dmabuf->file = file;
ret = dma_buf_stats_setup(dmabuf);
if (ret)
goto err_sysfs;
mutex_init(&dmabuf->lock); mutex_init(&dmabuf->lock);
INIT_LIST_HEAD(&dmabuf->attachments); INIT_LIST_HEAD(&dmabuf->attachments);
@@ -632,6 +636,10 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
list_add(&dmabuf->list_node, &db_list.head); list_add(&dmabuf->list_node, &db_list.head);
mutex_unlock(&db_list.lock); mutex_unlock(&db_list.lock);
ret = dma_buf_stats_setup(dmabuf);
if (ret)
goto err_sysfs;
return dmabuf; return dmabuf;
err_sysfs: err_sysfs:

View File

@@ -25,12 +25,16 @@
static struct kmem_cache *ino_entry_slab; static struct kmem_cache *ino_entry_slab;
struct kmem_cache *f2fs_inode_entry_slab; struct kmem_cache *f2fs_inode_entry_slab;
void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io) void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io,
unsigned char reason)
{ {
f2fs_build_fault_attr(sbi, 0, 0); f2fs_build_fault_attr(sbi, 0, 0);
set_ckpt_flags(sbi, CP_ERROR_FLAG); set_ckpt_flags(sbi, CP_ERROR_FLAG);
if (!end_io) if (!end_io) {
f2fs_flush_merged_writes(sbi); f2fs_flush_merged_writes(sbi);
f2fs_handle_stop(sbi, reason);
}
} }
/* /*
@@ -120,7 +124,7 @@ retry:
if (PTR_ERR(page) == -EIO && if (PTR_ERR(page) == -EIO &&
++count <= DEFAULT_RETRY_IO_COUNT) ++count <= DEFAULT_RETRY_IO_COUNT)
goto retry; goto retry;
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_META_PAGE);
} }
return page; return page;
} }

View File

@@ -311,7 +311,8 @@ static void f2fs_write_end_io(struct bio *bio)
mempool_free(page, sbi->write_io_dummy); mempool_free(page, sbi->write_io_dummy);
if (unlikely(bio->bi_status)) if (unlikely(bio->bi_status))
f2fs_stop_checkpoint(sbi, true); f2fs_stop_checkpoint(sbi, true,
STOP_CP_REASON_WRITE_FAIL);
continue; continue;
} }
@@ -327,7 +328,8 @@ static void f2fs_write_end_io(struct bio *bio)
if (unlikely(bio->bi_status)) { if (unlikely(bio->bi_status)) {
mapping_set_error(page->mapping, -EIO); mapping_set_error(page->mapping, -EIO);
if (type == F2FS_WB_CP_DATA) if (type == F2FS_WB_CP_DATA)
f2fs_stop_checkpoint(sbi, true); f2fs_stop_checkpoint(sbi, true,
STOP_CP_REASON_WRITE_FAIL);
} }
f2fs_bug_on(sbi, page->mapping == NODE_MAPPING(sbi) && f2fs_bug_on(sbi, page->mapping == NODE_MAPPING(sbi) &&

View File

@@ -3482,6 +3482,7 @@ int f2fs_enable_quota_files(struct f2fs_sb_info *sbi, bool rdonly);
int f2fs_quota_sync(struct super_block *sb, int type); int f2fs_quota_sync(struct super_block *sb, int type);
loff_t max_file_blocks(struct inode *inode); loff_t max_file_blocks(struct inode *inode);
void f2fs_quota_off_umount(struct super_block *sb); void f2fs_quota_off_umount(struct super_block *sb);
void f2fs_handle_stop(struct f2fs_sb_info *sbi, unsigned char reason);
int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover); int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover);
int f2fs_sync_fs(struct super_block *sb, int sync); int f2fs_sync_fs(struct super_block *sb, int sync);
int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi); int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi);
@@ -3631,7 +3632,8 @@ unsigned int f2fs_usable_blks_in_seg(struct f2fs_sb_info *sbi,
/* /*
* checkpoint.c * checkpoint.c
*/ */
void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io); void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io,
unsigned char reason);
void f2fs_flush_ckpt_thread(struct f2fs_sb_info *sbi); void f2fs_flush_ckpt_thread(struct f2fs_sb_info *sbi);
struct page *f2fs_grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index); struct page *f2fs_grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index);
struct page *f2fs_get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index); struct page *f2fs_get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index);

View File

@@ -2249,7 +2249,8 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
if (ret) { if (ret) {
if (ret == -EROFS) { if (ret == -EROFS) {
ret = 0; ret = 0;
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false,
STOP_CP_REASON_SHUTDOWN);
set_sbi_flag(sbi, SBI_IS_SHUTDOWN); set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
trace_f2fs_shutdown(sbi, in, ret); trace_f2fs_shutdown(sbi, in, ret);
} }
@@ -2262,7 +2263,7 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
ret = freeze_bdev(sb->s_bdev); ret = freeze_bdev(sb->s_bdev);
if (ret) if (ret)
goto out; goto out;
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN);
set_sbi_flag(sbi, SBI_IS_SHUTDOWN); set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
thaw_bdev(sb->s_bdev); thaw_bdev(sb->s_bdev);
break; break;
@@ -2271,16 +2272,16 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
ret = f2fs_sync_fs(sb, 1); ret = f2fs_sync_fs(sb, 1);
if (ret) if (ret)
goto out; goto out;
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN);
set_sbi_flag(sbi, SBI_IS_SHUTDOWN); set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
break; break;
case F2FS_GOING_DOWN_NOSYNC: case F2FS_GOING_DOWN_NOSYNC:
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN);
set_sbi_flag(sbi, SBI_IS_SHUTDOWN); set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
break; break;
case F2FS_GOING_DOWN_METAFLUSH: case F2FS_GOING_DOWN_METAFLUSH:
f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_META_IO); f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_META_IO);
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN);
set_sbi_flag(sbi, SBI_IS_SHUTDOWN); set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
break; break;
case F2FS_GOING_DOWN_NEED_FSCK: case F2FS_GOING_DOWN_NEED_FSCK:

View File

@@ -68,7 +68,8 @@ static int gc_thread_func(void *data)
if (time_to_inject(sbi, FAULT_CHECKPOINT)) { if (time_to_inject(sbi, FAULT_CHECKPOINT)) {
f2fs_show_injection_info(sbi, FAULT_CHECKPOINT); f2fs_show_injection_info(sbi, FAULT_CHECKPOINT);
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false,
STOP_CP_REASON_FAULT_INJECT);
} }
if (!sb_start_write_trylock(sbi->sb)) { if (!sb_start_write_trylock(sbi->sb)) {
@@ -1634,7 +1635,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
f2fs_err(sbi, "Inconsistent segment (%u) type [%d, %d] in SSA and SIT", f2fs_err(sbi, "Inconsistent segment (%u) type [%d, %d] in SSA and SIT",
segno, type, GET_SUM_TYPE((&sum->footer))); segno, type, GET_SUM_TYPE((&sum->footer)));
set_sbi_flag(sbi, SBI_NEED_FSCK); set_sbi_flag(sbi, SBI_NEED_FSCK);
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false,
STOP_CP_REASON_CORRUPTED_SUMMARY);
goto skip; goto skip;
} }

View File

@@ -685,7 +685,8 @@ retry:
cond_resched(); cond_resched();
goto retry; goto retry;
} else if (err != -ENOENT) { } else if (err != -ENOENT) {
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false,
STOP_CP_REASON_UPDATE_INODE);
} }
return; return;
} }

View File

@@ -499,7 +499,7 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need)
{ {
if (time_to_inject(sbi, FAULT_CHECKPOINT)) { if (time_to_inject(sbi, FAULT_CHECKPOINT)) {
f2fs_show_injection_info(sbi, FAULT_CHECKPOINT); f2fs_show_injection_info(sbi, FAULT_CHECKPOINT);
f2fs_stop_checkpoint(sbi, false); f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_FAULT_INJECT);
} }
/* balance_fs_bg is able to be pending */ /* balance_fs_bg is able to be pending */
@@ -782,8 +782,11 @@ int f2fs_flush_device_cache(struct f2fs_sb_info *sbi)
if (!f2fs_test_bit(i, (char *)&sbi->dirty_device)) if (!f2fs_test_bit(i, (char *)&sbi->dirty_device))
continue; continue;
ret = __submit_flush_wait(sbi, FDEV(i).bdev); ret = __submit_flush_wait(sbi, FDEV(i).bdev);
if (ret) if (ret) {
f2fs_stop_checkpoint(sbi, false,
STOP_CP_REASON_FLUSH_FAIL);
break; break;
}
spin_lock(&sbi->dev_lock); spin_lock(&sbi->dev_lock);
f2fs_clear_bit(i, (char *)&sbi->dirty_device); f2fs_clear_bit(i, (char *)&sbi->dirty_device);

View File

@@ -3642,6 +3642,26 @@ int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover)
return err; return err;
} }
void f2fs_handle_stop(struct f2fs_sb_info *sbi, unsigned char reason)
{
struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
int err;
f2fs_bug_on(sbi, reason >= MAX_STOP_REASON);
f2fs_down_write(&sbi->sb_lock);
if (raw_super->s_stop_reason[reason] < ((1 << BITS_PER_BYTE) - 1))
raw_super->s_stop_reason[reason]++;
err = f2fs_commit_super(sbi, false);
if (err)
f2fs_err(sbi, "f2fs_commit_super fails to record reason:%u err:%d",
reason, err);
f2fs_up_write(&sbi->sb_lock);
}
static int f2fs_scan_devices(struct f2fs_sb_info *sbi) static int f2fs_scan_devices(struct f2fs_sb_info *sbi)
{ {
struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);

View File

@@ -73,6 +73,20 @@ struct f2fs_device {
__le32 total_segments; __le32 total_segments;
} __packed; } __packed;
/* reason of stop_checkpoint */
enum stop_cp_reason {
STOP_CP_REASON_SHUTDOWN,
STOP_CP_REASON_FAULT_INJECT,
STOP_CP_REASON_META_PAGE,
STOP_CP_REASON_WRITE_FAIL,
STOP_CP_REASON_CORRUPTED_SUMMARY,
STOP_CP_REASON_UPDATE_INODE,
STOP_CP_REASON_FLUSH_FAIL,
STOP_CP_REASON_MAX,
};
#define MAX_STOP_REASON 32
struct f2fs_super_block { struct f2fs_super_block {
__le32 magic; /* Magic Number */ __le32 magic; /* Magic Number */
__le16 major_ver; /* Major Version */ __le16 major_ver; /* Major Version */
@@ -116,7 +130,8 @@ struct f2fs_super_block {
__u8 hot_ext_count; /* # of hot file extension */ __u8 hot_ext_count; /* # of hot file extension */
__le16 s_encoding; /* Filename charset encoding */ __le16 s_encoding; /* Filename charset encoding */
__le16 s_encoding_flags; /* Filename charset encoding flags */ __le16 s_encoding_flags; /* Filename charset encoding flags */
__u8 reserved[306]; /* valid reserved region */ __u8 s_stop_reason[MAX_STOP_REASON]; /* stop checkpoint reason */
__u8 reserved[274]; /* valid reserved region */
__le32 crc; /* checksum of superblock */ __le32 crc; /* checksum of superblock */
} __packed; } __packed;

View File

@@ -515,6 +515,11 @@ static inline void i_mmap_unlock_write(struct address_space *mapping)
up_write(&mapping->i_mmap_rwsem); up_write(&mapping->i_mmap_rwsem);
} }
static inline int i_mmap_trylock_read(struct address_space *mapping)
{
return down_read_trylock(&mapping->i_mmap_rwsem);
}
static inline void i_mmap_lock_read(struct address_space *mapping) static inline void i_mmap_lock_read(struct address_space *mapping)
{ {
down_read(&mapping->i_mmap_rwsem); down_read(&mapping->i_mmap_rwsem);

View File

@@ -134,6 +134,11 @@ static inline void anon_vma_lock_read(struct anon_vma *anon_vma)
down_read(&anon_vma->root->rwsem); down_read(&anon_vma->root->rwsem);
} }
static inline int anon_vma_trylock_read(struct anon_vma *anon_vma)
{
return down_read_trylock(&anon_vma->root->rwsem);
}
static inline void anon_vma_unlock_read(struct anon_vma *anon_vma) static inline void anon_vma_unlock_read(struct anon_vma *anon_vma)
{ {
up_read(&anon_vma->root->rwsem); up_read(&anon_vma->root->rwsem);
@@ -261,17 +266,14 @@ void try_to_munlock(struct page *);
void remove_migration_ptes(struct page *old, struct page *new, bool locked); void remove_migration_ptes(struct page *old, struct page *new, bool locked);
/*
* Called by memory-failure.c to kill processes.
*/
struct anon_vma *page_lock_anon_vma_read(struct page *page);
void page_unlock_anon_vma_read(struct anon_vma *anon_vma);
int page_mapped_in_vma(struct page *page, struct vm_area_struct *vma); int page_mapped_in_vma(struct page *page, struct vm_area_struct *vma);
/* /*
* rmap_walk_control: To control rmap traversing for specific needs * rmap_walk_control: To control rmap traversing for specific needs
* *
* arg: passed to rmap_one() and invalid_vma() * arg: passed to rmap_one() and invalid_vma()
* try_lock: bail out if the rmap lock is contended
* contended: indicate the rmap traversal bailed out due to lock contention
* rmap_one: executed on each vma where page is mapped * rmap_one: executed on each vma where page is mapped
* done: for checking traversing termination condition * done: for checking traversing termination condition
* anon_lock: for getting anon_lock by optimized way rather than default * anon_lock: for getting anon_lock by optimized way rather than default
@@ -279,6 +281,8 @@ int page_mapped_in_vma(struct page *page, struct vm_area_struct *vma);
*/ */
struct rmap_walk_control { struct rmap_walk_control {
void *arg; void *arg;
bool try_lock;
bool contended;
/* /*
* Return false if page table scanning in rmap_walk should be stopped. * Return false if page table scanning in rmap_walk should be stopped.
* Otherwise, return true. * Otherwise, return true.
@@ -286,13 +290,21 @@ struct rmap_walk_control {
bool (*rmap_one)(struct page *page, struct vm_area_struct *vma, bool (*rmap_one)(struct page *page, struct vm_area_struct *vma,
unsigned long addr, void *arg); unsigned long addr, void *arg);
int (*done)(struct page *page); int (*done)(struct page *page);
struct anon_vma *(*anon_lock)(struct page *page); struct anon_vma *(*anon_lock)(struct page *page,
struct rmap_walk_control *rwc);
bool (*invalid_vma)(struct vm_area_struct *vma, void *arg); bool (*invalid_vma)(struct vm_area_struct *vma, void *arg);
}; };
void rmap_walk(struct page *page, struct rmap_walk_control *rwc); void rmap_walk(struct page *page, struct rmap_walk_control *rwc);
void rmap_walk_locked(struct page *page, struct rmap_walk_control *rwc); void rmap_walk_locked(struct page *page, struct rmap_walk_control *rwc);
/*
* Called by memory-failure.c to kill processes.
*/
struct anon_vma *page_lock_anon_vma_read(struct page *page,
struct rmap_walk_control *rwc);
void page_unlock_anon_vma_read(struct anon_vma *anon_vma);
#else /* !CONFIG_MMU */ #else /* !CONFIG_MMU */
#define anon_vma_init() do {} while (0) #define anon_vma_init() do {} while (0)

View File

@@ -193,6 +193,9 @@ DECLARE_HOOK(android_vh_subpage_dma_contig_alloc,
DECLARE_HOOK(android_vh_ra_tuning_max_page, DECLARE_HOOK(android_vh_ra_tuning_max_page,
TP_PROTO(struct readahead_control *ractl, unsigned long *max_page), TP_PROTO(struct readahead_control *ractl, unsigned long *max_page),
TP_ARGS(ractl, max_page)); TP_ARGS(ractl, max_page));
DECLARE_RESTRICTED_HOOK(android_rvh_handle_pte_fault_end,
TP_PROTO(struct vm_fault *vmf, unsigned long highest_memmap_pfn),
TP_ARGS(vmf, highest_memmap_pfn), 1);
DECLARE_HOOK(android_vh_handle_pte_fault_end, DECLARE_HOOK(android_vh_handle_pte_fault_end,
TP_PROTO(struct vm_fault *vmf, unsigned long highest_memmap_pfn), TP_PROTO(struct vm_fault *vmf, unsigned long highest_memmap_pfn),
TP_ARGS(vmf, highest_memmap_pfn)); TP_ARGS(vmf, highest_memmap_pfn));
@@ -223,16 +226,30 @@ DECLARE_HOOK(android_vh_count_swpout_vm_event,
DECLARE_HOOK(android_vh_swap_slot_cache_active, DECLARE_HOOK(android_vh_swap_slot_cache_active,
TP_PROTO(bool swap_slot_cache_active), TP_PROTO(bool swap_slot_cache_active),
TP_ARGS(swap_slot_cache_active)); TP_ARGS(swap_slot_cache_active));
DECLARE_RESTRICTED_HOOK(android_rvh_drain_slots_cache_cpu,
TP_PROTO(struct swap_slots_cache *cache, unsigned int type,
bool free_slots, bool *skip),
TP_ARGS(cache, type, free_slots, skip), 1);
DECLARE_HOOK(android_vh_drain_slots_cache_cpu, DECLARE_HOOK(android_vh_drain_slots_cache_cpu,
TP_PROTO(struct swap_slots_cache *cache, unsigned int type, TP_PROTO(struct swap_slots_cache *cache, unsigned int type,
bool free_slots, bool *skip), bool free_slots, bool *skip),
TP_ARGS(cache, type, free_slots, skip)); TP_ARGS(cache, type, free_slots, skip));
DECLARE_RESTRICTED_HOOK(android_rvh_alloc_swap_slot_cache,
TP_PROTO(struct swap_slots_cache *cache, int *ret, bool *skip),
TP_ARGS(cache, ret, skip), 1);
DECLARE_HOOK(android_vh_alloc_swap_slot_cache, DECLARE_HOOK(android_vh_alloc_swap_slot_cache,
TP_PROTO(struct swap_slots_cache *cache, int *ret, bool *skip), TP_PROTO(struct swap_slots_cache *cache, int *ret, bool *skip),
TP_ARGS(cache, ret, skip)); TP_ARGS(cache, ret, skip));
DECLARE_RESTRICTED_HOOK(android_rvh_free_swap_slot,
TP_PROTO(swp_entry_t entry, struct swap_slots_cache *cache, bool *skip),
TP_ARGS(entry, cache, skip), 1);
DECLARE_HOOK(android_vh_free_swap_slot, DECLARE_HOOK(android_vh_free_swap_slot,
TP_PROTO(swp_entry_t entry, struct swap_slots_cache *cache, bool *skip), TP_PROTO(swp_entry_t entry, struct swap_slots_cache *cache, bool *skip),
TP_ARGS(entry, cache, skip)); TP_ARGS(entry, cache, skip));
DECLARE_RESTRICTED_HOOK(android_rvh_get_swap_page,
TP_PROTO(struct page *page, swp_entry_t *entry,
struct swap_slots_cache *cache, bool *found),
TP_ARGS(page, entry, cache, found), 1);
DECLARE_HOOK(android_vh_get_swap_page, DECLARE_HOOK(android_vh_get_swap_page,
TP_PROTO(struct page *page, swp_entry_t *entry, TP_PROTO(struct page *page, swp_entry_t *entry,
struct swap_slots_cache *cache, bool *found), struct swap_slots_cache *cache, bool *found),
@@ -255,6 +272,9 @@ DECLARE_HOOK(android_vh_init_swap_info_struct,
DECLARE_HOOK(android_vh_si_swapinfo, DECLARE_HOOK(android_vh_si_swapinfo,
TP_PROTO(struct swap_info_struct *si, bool *skip), TP_PROTO(struct swap_info_struct *si, bool *skip),
TP_ARGS(si, skip)); TP_ARGS(si, skip));
DECLARE_RESTRICTED_HOOK(android_rvh_alloc_si,
TP_PROTO(struct swap_info_struct **p, bool *skip),
TP_ARGS(p, skip), 1);
DECLARE_HOOK(android_vh_alloc_si, DECLARE_HOOK(android_vh_alloc_si,
TP_PROTO(struct swap_info_struct **p, bool *skip), TP_PROTO(struct swap_info_struct **p, bool *skip),
TP_ARGS(p, skip)); TP_ARGS(p, skip));

View File

@@ -1865,7 +1865,9 @@ int __boot_cpu_id;
/* Horrific hacks because we can't add more to cpuhp_hp_states. */ /* Horrific hacks because we can't add more to cpuhp_hp_states. */
static int random_and_perf_prepare_fusion(unsigned int cpu) static int random_and_perf_prepare_fusion(unsigned int cpu)
{ {
#ifdef CONFIG_PERF_EVENTS
perf_event_init_cpu(cpu); perf_event_init_cpu(cpu);
#endif
random_prepare_cpu(cpu); random_prepare_cpu(cpu);
return 0; return 0;
} }

View File

@@ -1020,7 +1020,7 @@ void psi_cgroup_free(struct cgroup *cgroup)
*/ */
void cgroup_move_task(struct task_struct *task, struct css_set *to) void cgroup_move_task(struct task_struct *task, struct css_set *to)
{ {
unsigned int task_flags = 0; unsigned int task_flags;
struct rq_flags rf; struct rq_flags rf;
struct rq *rq; struct rq *rq;
@@ -1035,15 +1035,31 @@ void cgroup_move_task(struct task_struct *task, struct css_set *to)
rq = task_rq_lock(task, &rf); rq = task_rq_lock(task, &rf);
if (task_on_rq_queued(task)) { /*
task_flags = TSK_RUNNING; * We may race with schedule() dropping the rq lock between
if (task_current(rq, task)) * deactivating prev and switching to next. Because the psi
task_flags |= TSK_ONCPU; * updates from the deactivation are deferred to the switch
} else if (task->in_iowait) * callback to save cgroup tree updates, the task's scheduling
task_flags = TSK_IOWAIT; * state here is not coherent with its psi state:
*
if (task->in_memstall) * schedule() cgroup_move_task()
task_flags |= TSK_MEMSTALL; * rq_lock()
* deactivate_task()
* p->on_rq = 0
* psi_dequeue() // defers TSK_RUNNING & TSK_IOWAIT updates
* pick_next_task()
* rq_unlock()
* rq_lock()
* psi_task_change() // old cgroup
* task->cgroups = to
* psi_task_change() // new cgroup
* rq_unlock()
* rq_lock()
* psi_sched_switch() // does deferred updates in new cgroup
*
* Don't rely on the scheduling state. Use psi_flags instead.
*/
task_flags = task->psi_flags;
if (task_flags) if (task_flags)
psi_task_change(task, task_flags, 0); psi_task_change(task, task_flags, 0);

View File

@@ -1481,7 +1481,7 @@ vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t pmd)
*/ */
get_page(page); get_page(page);
spin_unlock(vmf->ptl); spin_unlock(vmf->ptl);
anon_vma = page_lock_anon_vma_read(page); anon_vma = page_lock_anon_vma_read(page, NULL);
/* Confirm the PMD did not change while page_table_lock was released */ /* Confirm the PMD did not change while page_table_lock was released */
spin_lock(vmf->ptl); spin_lock(vmf->ptl);

View File

@@ -2626,7 +2626,13 @@ again:
struct vm_area_struct *vma; struct vm_area_struct *vma;
cond_resched(); cond_resched();
if (!anon_vma_trylock_read(anon_vma)) {
if (rwc->try_lock) {
rwc->contended = true;
return;
}
anon_vma_lock_read(anon_vma); anon_vma_lock_read(anon_vma);
}
anon_vma_interval_tree_foreach(vmac, &anon_vma->rb_root, anon_vma_interval_tree_foreach(vmac, &anon_vma->rb_root,
0, ULONG_MAX) { 0, ULONG_MAX) {
unsigned long addr; unsigned long addr;

View File

@@ -477,7 +477,7 @@ static void collect_procs_anon(struct page *page, struct list_head *to_kill,
struct anon_vma *av; struct anon_vma *av;
pgoff_t pgoff; pgoff_t pgoff;
av = page_lock_anon_vma_read(page); av = page_lock_anon_vma_read(page, NULL);
if (av == NULL) /* Not actually mapped anymore */ if (av == NULL) /* Not actually mapped anymore */
return; return;

View File

@@ -4777,6 +4777,7 @@ static vm_fault_t handle_pte_fault(struct vm_fault *vmf)
if (vmf->flags & FAULT_FLAG_WRITE) if (vmf->flags & FAULT_FLAG_WRITE)
flush_tlb_fix_spurious_fault(vmf->vma, vmf->address); flush_tlb_fix_spurious_fault(vmf->vma, vmf->address);
} }
trace_android_rvh_handle_pte_fault_end(vmf, highest_memmap_pfn);
trace_android_vh_handle_pte_fault_end(vmf, highest_memmap_pfn); trace_android_vh_handle_pte_fault_end(vmf, highest_memmap_pfn);
unlock: unlock:
pte_unmap_unlock(vmf->pte, vmf->ptl); pte_unmap_unlock(vmf->pte, vmf->ptl);

View File

@@ -92,10 +92,10 @@ static bool page_idle_clear_pte_refs_one(struct page *page,
static void page_idle_clear_pte_refs(struct page *page) static void page_idle_clear_pte_refs(struct page *page)
{ {
/* /*
* Since rwc.arg is unused, rwc is effectively immutable, so we * Since rwc.try_lock is unused, rwc is effectively immutable, so we
* can make it static const to save some cycles and stack. * can make it static to save some cycles and stack.
*/ */
static const struct rmap_walk_control rwc = { static struct rmap_walk_control rwc = {
.rmap_one = page_idle_clear_pte_refs_one, .rmap_one = page_idle_clear_pte_refs_one,
.anon_lock = page_lock_anon_vma_read, .anon_lock = page_lock_anon_vma_read,
}; };

View File

@@ -518,9 +518,11 @@ out:
* *
* Its a little more complex as it tries to keep the fast path to a single * Its a little more complex as it tries to keep the fast path to a single
* atomic op -- the trylock. If we fail the trylock, we fall back to getting a * atomic op -- the trylock. If we fail the trylock, we fall back to getting a
* reference like with page_get_anon_vma() and then block on the mutex. * reference like with page_get_anon_vma() and then block on the mutex
* on !rwc->try_lock case.
*/ */
struct anon_vma *page_lock_anon_vma_read(struct page *page) struct anon_vma *page_lock_anon_vma_read(struct page *page,
struct rmap_walk_control *rwc)
{ {
struct anon_vma *anon_vma = NULL; struct anon_vma *anon_vma = NULL;
struct anon_vma *root_anon_vma; struct anon_vma *root_anon_vma;
@@ -553,6 +555,13 @@ struct anon_vma *page_lock_anon_vma_read(struct page *page)
anon_vma = NULL; anon_vma = NULL;
goto out; goto out;
} }
if (rwc && rwc->try_lock) {
anon_vma = NULL;
rwc->contended = true;
goto out;
}
/* trylock failed, we got to sleep */ /* trylock failed, we got to sleep */
if (!atomic_inc_not_zero(&anon_vma->refcount)) { if (!atomic_inc_not_zero(&anon_vma->refcount)) {
anon_vma = NULL; anon_vma = NULL;
@@ -850,8 +859,10 @@ static bool invalid_page_referenced_vma(struct vm_area_struct *vma, void *arg)
* @memcg: target memory cgroup * @memcg: target memory cgroup
* @vm_flags: collect encountered vma->vm_flags who actually referenced the page * @vm_flags: collect encountered vma->vm_flags who actually referenced the page
* *
* Quick test_and_clear_referenced for all mappings to a page, * Quick test_and_clear_referenced for all mappings of a page,
* returns the number of ptes which referenced the page. *
* Return: The number of mappings which referenced the page. Return -1 if
* the function bailed out due to rmap lock contention.
*/ */
int page_referenced(struct page *page, int page_referenced(struct page *page,
int is_locked, int is_locked,
@@ -867,6 +878,7 @@ int page_referenced(struct page *page,
.rmap_one = page_referenced_one, .rmap_one = page_referenced_one,
.arg = (void *)&pra, .arg = (void *)&pra,
.anon_lock = page_lock_anon_vma_read, .anon_lock = page_lock_anon_vma_read,
.try_lock = true,
}; };
*vm_flags = 0; *vm_flags = 0;
@@ -897,7 +909,7 @@ int page_referenced(struct page *page,
if (we_locked) if (we_locked)
unlock_page(page); unlock_page(page);
return pra.referenced; return rwc.contended ? -1 : pra.referenced;
} }
static bool page_mkclean_one(struct page *page, struct vm_area_struct *vma, static bool page_mkclean_one(struct page *page, struct vm_area_struct *vma,
@@ -1898,7 +1910,7 @@ static struct anon_vma *rmap_walk_anon_lock(struct page *page,
struct anon_vma *anon_vma; struct anon_vma *anon_vma;
if (rwc->anon_lock) if (rwc->anon_lock)
return rwc->anon_lock(page); return rwc->anon_lock(page, rwc);
/* /*
* Note: remove_migration_ptes() cannot use page_lock_anon_vma_read() * Note: remove_migration_ptes() cannot use page_lock_anon_vma_read()
@@ -1910,7 +1922,17 @@ static struct anon_vma *rmap_walk_anon_lock(struct page *page,
if (!anon_vma) if (!anon_vma)
return NULL; return NULL;
if (anon_vma_trylock_read(anon_vma))
goto out;
if (rwc->try_lock) {
anon_vma = NULL;
rwc->contended = true;
goto out;
}
anon_vma_lock_read(anon_vma); anon_vma_lock_read(anon_vma);
out:
return anon_vma; return anon_vma;
} }
@@ -2009,9 +2031,18 @@ static void rmap_walk_file(struct page *page, struct rmap_walk_control *rwc,
if (!got_lock) if (!got_lock)
return; return;
} else { } else {
if (i_mmap_trylock_read(mapping))
goto lookup;
if (rwc->try_lock) {
rwc->contended = true;
return;
}
i_mmap_lock_read(mapping); i_mmap_lock_read(mapping);
} }
} }
lookup:
vma_interval_tree_foreach(vma, &mapping->i_mmap, vma_interval_tree_foreach(vma, &mapping->i_mmap,
pgoff_start, pgoff_end) { pgoff_start, pgoff_end) {
unsigned long address = vma_address(page, vma); unsigned long address = vma_address(page, vma);

View File

@@ -133,6 +133,8 @@ static int alloc_swap_slot_cache(unsigned int cpu)
* as kvzalloc could trigger reclaim and get_swap_page, * as kvzalloc could trigger reclaim and get_swap_page,
* which can lock swap_slots_cache_mutex. * which can lock swap_slots_cache_mutex.
*/ */
trace_android_rvh_alloc_swap_slot_cache(&per_cpu(swp_slots, cpu),
&ret, &skip);
trace_android_vh_alloc_swap_slot_cache(&per_cpu(swp_slots, cpu), trace_android_vh_alloc_swap_slot_cache(&per_cpu(swp_slots, cpu),
&ret, &skip); &ret, &skip);
if (skip) if (skip)
@@ -190,6 +192,8 @@ static void drain_slots_cache_cpu(unsigned int cpu, unsigned int type,
bool skip = false; bool skip = false;
cache = &per_cpu(swp_slots, cpu); cache = &per_cpu(swp_slots, cpu);
trace_android_rvh_drain_slots_cache_cpu(cache, type,
free_slots, &skip);
trace_android_vh_drain_slots_cache_cpu(cache, type, trace_android_vh_drain_slots_cache_cpu(cache, type,
free_slots, &skip); free_slots, &skip);
if (skip) if (skip)
@@ -298,6 +302,7 @@ int free_swap_slot(swp_entry_t entry)
bool skip = false; bool skip = false;
cache = raw_cpu_ptr(&swp_slots); cache = raw_cpu_ptr(&swp_slots);
trace_android_rvh_free_swap_slot(entry, cache, &skip);
trace_android_vh_free_swap_slot(entry, cache, &skip); trace_android_vh_free_swap_slot(entry, cache, &skip);
if (skip) if (skip)
return 0; return 0;
@@ -335,6 +340,7 @@ swp_entry_t get_swap_page(struct page *page)
bool found = false; bool found = false;
entry.val = 0; entry.val = 0;
trace_android_rvh_get_swap_page(page, &entry, raw_cpu_ptr(&swp_slots), &found);
trace_android_vh_get_swap_page(page, &entry, raw_cpu_ptr(&swp_slots), &found); trace_android_vh_get_swap_page(page, &entry, raw_cpu_ptr(&swp_slots), &found);
if (found) if (found)
goto out; goto out;

View File

@@ -2908,6 +2908,7 @@ static struct swap_info_struct *alloc_swap_info(void)
int i; int i;
bool skip = false; bool skip = false;
trace_android_rvh_alloc_si(&p, &skip);
trace_android_vh_alloc_si(&p, &skip); trace_android_vh_alloc_si(&p, &skip);
if (!skip) if (!skip)
p = kvzalloc(struct_size(p, avail_lists, nr_node_ids), GFP_KERNEL); p = kvzalloc(struct_size(p, avail_lists, nr_node_ids), GFP_KERNEL);

View File

@@ -1045,6 +1045,10 @@ static enum page_references page_check_references(struct page *page,
if (vm_flags & VM_LOCKED) if (vm_flags & VM_LOCKED)
return PAGEREF_RECLAIM; return PAGEREF_RECLAIM;
/* rmap lock contention: rotate */
if (referenced_ptes == -1)
return PAGEREF_KEEP;
if (referenced_ptes) { if (referenced_ptes) {
/* /*
* All mapped pages start out with page table * All mapped pages start out with page table
@@ -1348,7 +1352,7 @@ static unsigned int shrink_page_list(struct list_head *page_list,
if (unlikely(PageTransHuge(page))) if (unlikely(PageTransHuge(page)))
flags |= TTU_SPLIT_HUGE_PMD; flags |= TTU_SPLIT_HUGE_PMD;
if (!ignore_references)
trace_android_vh_page_trylock_set(page); trace_android_vh_page_trylock_set(page);
if (!try_to_unmap(page, flags)) { if (!try_to_unmap(page, flags)) {
stat->nr_unmap_fail += nr_pages; stat->nr_unmap_fail += nr_pages;
@@ -2119,8 +2123,9 @@ static void shrink_active_list(unsigned long nr_to_scan,
if (bypass) if (bypass)
goto skip_page_referenced; goto skip_page_referenced;
trace_android_vh_page_trylock_set(page); trace_android_vh_page_trylock_set(page);
/* Referenced or rmap lock contention: rotate */
if (page_referenced(page, 0, sc->target_mem_cgroup, if (page_referenced(page, 0, sc->target_mem_cgroup,
&vm_flags)) { &vm_flags) != 0) {
/* /*
* Identify referenced, file-backed active pages and * Identify referenced, file-backed active pages and
* give them one more trip around the active list. So * give them one more trip around the active list. So