Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

of: overlay: unittest: add tests for overlay notifiers

Add tests for overlay apply and remove notifiers. Trigger errors
for each of the notifier actions.

These tests will reveal a memory leak problem when a notifier returns
an error for action OF_OVERLAY_POST_APPLY. The pr_err() message is:

OF: ERROR: memory leak, expected refcount 1 instead of 3,
of_node_get()/of_node_put() unbalanced - destroy cset entry: attach
overlay node /testcase-data/overlay-node/test-bus/test-unittest17

Signed-off-by: Frank Rowand <frank.rowand@sony.com>
Signed-off-by: Rob Herring <robh@kernel.org>
Link: https://lore.kernel.org/r/20220502181742.1402826-3-frowand.list@gmail.com

authored by

Frank Rowand and committed by
Rob Herring
992b0dc5 1ac17586

+280
+10
drivers/of/unittest-data/Makefile
··· 17 17 overlay_12.dtb.o \ 18 18 overlay_13.dtb.o \ 19 19 overlay_15.dtb.o \ 20 + overlay_16.dtb.o \ 21 + overlay_17.dtb.o \ 22 + overlay_18.dtb.o \ 23 + overlay_19.dtb.o \ 24 + overlay_20.dtb.o \ 20 25 overlay_bad_add_dup_node.dtb.o \ 21 26 overlay_bad_add_dup_prop.dtb.o \ 22 27 overlay_bad_phandle.dtb.o \ ··· 80 75 overlay_12.dtbo \ 81 76 overlay_13.dtbo \ 82 77 overlay_15.dtbo \ 78 + overlay_16.dtbo \ 79 + overlay_17.dtbo \ 80 + overlay_18.dtbo \ 81 + overlay_19.dtbo \ 82 + overlay_20.dtbo \ 83 83 overlay_gpio_01.dtbo \ 84 84 overlay_gpio_02a.dtbo \ 85 85 overlay_gpio_02b.dtbo \
+15
drivers/of/unittest-data/overlay_16.dts
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /dts-v1/; 3 + /plugin/; 4 + 5 + /* overlay_16 - notify test */ 6 + 7 + &unittest_test_bus { 8 + #address-cells = <1>; 9 + #size-cells = <0>; 10 + 11 + test-unittest16 { 12 + compatible = "unittest"; 13 + reg = <16>; 14 + }; 15 + };
+15
drivers/of/unittest-data/overlay_17.dts
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /dts-v1/; 3 + /plugin/; 4 + 5 + /* overlay_17 - notify test */ 6 + 7 + &unittest_test_bus { 8 + #address-cells = <1>; 9 + #size-cells = <0>; 10 + 11 + test-unittest17 { 12 + compatible = "unittest"; 13 + reg = <17>; 14 + }; 15 + };
+15
drivers/of/unittest-data/overlay_18.dts
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /dts-v1/; 3 + /plugin/; 4 + 5 + /* overlay_18 - notify test */ 6 + 7 + &unittest_test_bus { 8 + #address-cells = <1>; 9 + #size-cells = <0>; 10 + 11 + test-unittest18 { 12 + compatible = "unittest"; 13 + reg = <18>; 14 + }; 15 + };
+15
drivers/of/unittest-data/overlay_19.dts
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /dts-v1/; 3 + /plugin/; 4 + 5 + /* overlay_19 - notify test */ 6 + 7 + &unittest_test_bus { 8 + #address-cells = <1>; 9 + #size-cells = <0>; 10 + 11 + test-unittest19 { 12 + compatible = "unittest"; 13 + reg = <19>; 14 + }; 15 + };
+15
drivers/of/unittest-data/overlay_20.dts
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /dts-v1/; 3 + /plugin/; 4 + 5 + /* overlay_20 - notify test */ 6 + 7 + &unittest_test_bus { 8 + #address-cells = <1>; 9 + #size-cells = <0>; 10 + 11 + test-unittest20 { 12 + compatible = "unittest"; 13 + reg = <20>; 14 + }; 15 + };
+195
drivers/of/unittest.c
··· 2741 2741 2742 2742 #endif 2743 2743 2744 + static int of_notify(struct notifier_block *nb, unsigned long action, 2745 + void *arg) 2746 + { 2747 + struct of_overlay_notify_data *nd = arg; 2748 + struct device_node *found; 2749 + int ret; 2750 + 2751 + /* 2752 + * For overlay_16 .. overlay_19, check that returning an error 2753 + * works for each of the actions by setting an arbitrary return 2754 + * error number that matches the test number. e.g. for unittest16, 2755 + * ret = -EBUSY which is -16. 2756 + * 2757 + * OVERLAY_INFO() for the overlays is declared to expect the same 2758 + * error number, so overlay_data_apply() will return no error. 2759 + * 2760 + * overlay_20 will return NOTIFY_DONE 2761 + */ 2762 + 2763 + ret = 0; 2764 + of_node_get(nd->overlay); 2765 + 2766 + switch (action) { 2767 + 2768 + case OF_OVERLAY_PRE_APPLY: 2769 + found = of_find_node_by_name(nd->overlay, "test-unittest16"); 2770 + if (found) { 2771 + of_node_put(found); 2772 + ret = -EBUSY; 2773 + } 2774 + break; 2775 + 2776 + case OF_OVERLAY_POST_APPLY: 2777 + found = of_find_node_by_name(nd->overlay, "test-unittest17"); 2778 + if (found) { 2779 + of_node_put(found); 2780 + ret = -EEXIST; 2781 + } 2782 + break; 2783 + 2784 + case OF_OVERLAY_PRE_REMOVE: 2785 + found = of_find_node_by_name(nd->overlay, "test-unittest18"); 2786 + if (found) { 2787 + of_node_put(found); 2788 + ret = -EXDEV; 2789 + } 2790 + break; 2791 + 2792 + case OF_OVERLAY_POST_REMOVE: 2793 + found = of_find_node_by_name(nd->overlay, "test-unittest19"); 2794 + if (found) { 2795 + of_node_put(found); 2796 + ret = -ENODEV; 2797 + } 2798 + break; 2799 + 2800 + default: /* should not happen */ 2801 + of_node_put(nd->overlay); 2802 + ret = -EINVAL; 2803 + break; 2804 + } 2805 + 2806 + if (ret) 2807 + return notifier_from_errno(ret); 2808 + 2809 + return NOTIFY_DONE; 2810 + } 2811 + 2812 + static struct notifier_block of_nb = { 2813 + .notifier_call = of_notify, 2814 + }; 2815 + 2816 + static void __init of_unittest_overlay_notify(void) 2817 + { 2818 + int ovcs_id; 2819 + int ret; 2820 + 2821 + ret = of_overlay_notifier_register(&of_nb); 2822 + unittest(!ret, 2823 + "of_overlay_notifier_register() failed, ret = %d\n", ret); 2824 + if (ret) 2825 + return; 2826 + 2827 + /* 2828 + * The overlays are applied by overlay_data_apply() 2829 + * instead of of_unittest_apply_overlay() so that they 2830 + * will not be tracked. Thus they will not be removed 2831 + * by of_unittest_remove_tracked_overlays(). 2832 + * 2833 + * Applying overlays 16 - 19 will each trigger an error for a 2834 + * different action in of_notify(). 2835 + * 2836 + * Applying overlay 20 will not trigger any error in of_notify(). 2837 + */ 2838 + 2839 + /* --- overlay 16 --- */ 2840 + 2841 + EXPECT_BEGIN(KERN_INFO, "OF: overlay: overlay changeset pre-apply notifier error -16, target: /testcase-data/overlay-node/test-bus"); 2842 + 2843 + unittest(overlay_data_apply("overlay_16", &ovcs_id), 2844 + "test OF_OVERLAY_PRE_APPLY notify injected error\n"); 2845 + 2846 + EXPECT_END(KERN_INFO, "OF: overlay: overlay changeset pre-apply notifier error -16, target: /testcase-data/overlay-node/test-bus"); 2847 + 2848 + unittest(!ovcs_id, "ovcs_id created for overlay_16\n"); 2849 + 2850 + /* --- overlay 17 --- */ 2851 + 2852 + EXPECT_BEGIN(KERN_INFO, "OF: overlay: overlay changeset post-apply notifier error -17, target: /testcase-data/overlay-node/test-bus"); 2853 + 2854 + unittest(overlay_data_apply("overlay_17", &ovcs_id), 2855 + "test OF_OVERLAY_POST_APPLY notify injected error\n"); 2856 + 2857 + EXPECT_END(KERN_INFO, "OF: overlay: overlay changeset post-apply notifier error -17, target: /testcase-data/overlay-node/test-bus"); 2858 + 2859 + unittest(!ovcs_id, "ovcs_id created for overlay_17\n"); 2860 + 2861 + /* --- overlay 18 --- */ 2862 + 2863 + unittest(overlay_data_apply("overlay_18", &ovcs_id), 2864 + "OF_OVERLAY_PRE_REMOVE notify injected error\n"); 2865 + 2866 + unittest(ovcs_id, "ovcs_id not created for overlay_18\n"); 2867 + 2868 + if (ovcs_id) { 2869 + EXPECT_BEGIN(KERN_INFO, "OF: overlay: overlay changeset pre-remove notifier error -18, target: /testcase-data/overlay-node/test-bus"); 2870 + 2871 + ret = of_overlay_remove(&ovcs_id); 2872 + EXPECT_END(KERN_INFO, "OF: overlay: overlay changeset pre-remove notifier error -18, target: /testcase-data/overlay-node/test-bus"); 2873 + if (ret == -EXDEV) { 2874 + /* 2875 + * change set ovcs_id should still exist 2876 + */ 2877 + unittest(1, "overlay_18 of_overlay_remove() injected error for OF_OVERLAY_PRE_REMOVE\n"); 2878 + } else { 2879 + unittest(0, "overlay_18 of_overlay_remove() injected error for OF_OVERLAY_PRE_REMOVE not returned\n"); 2880 + } 2881 + } else { 2882 + unittest(1, "ovcs_id not created for overlay_18\n"); 2883 + } 2884 + 2885 + unittest(ovcs_id, "ovcs_id removed for overlay_18\n"); 2886 + 2887 + /* --- overlay 19 --- */ 2888 + 2889 + unittest(overlay_data_apply("overlay_19", &ovcs_id), 2890 + "OF_OVERLAY_POST_REMOVE notify injected error\n"); 2891 + 2892 + unittest(ovcs_id, "ovcs_id not created for overlay_19\n"); 2893 + 2894 + if (ovcs_id) { 2895 + EXPECT_BEGIN(KERN_INFO, "OF: overlay: overlay changeset post-remove notifier error -19, target: /testcase-data/overlay-node/test-bus"); 2896 + ret = of_overlay_remove(&ovcs_id); 2897 + EXPECT_END(KERN_INFO, "OF: overlay: overlay changeset post-remove notifier error -19, target: /testcase-data/overlay-node/test-bus"); 2898 + if (ret == -ENODEV) 2899 + unittest(1, "overlay_19 of_overlay_remove() injected error for OF_OVERLAY_POST_REMOVE\n"); 2900 + else 2901 + unittest(0, "overlay_19 of_overlay_remove() injected error for OF_OVERLAY_POST_REMOVE not returned\n"); 2902 + } else { 2903 + unittest(1, "ovcs_id removed for overlay_19\n"); 2904 + } 2905 + 2906 + unittest(!ovcs_id, "changeset ovcs_id = %d not removed for overlay_19\n", 2907 + ovcs_id); 2908 + 2909 + /* --- overlay 20 --- */ 2910 + 2911 + unittest(overlay_data_apply("overlay_20", &ovcs_id), 2912 + "overlay notify no injected error\n"); 2913 + 2914 + if (ovcs_id) { 2915 + ret = of_overlay_remove(&ovcs_id); 2916 + if (ret) 2917 + unittest(1, "overlay_20 failed to be destroyed, ret = %d\n", 2918 + ret); 2919 + } else { 2920 + unittest(1, "ovcs_id not created for overlay_20\n"); 2921 + } 2922 + 2923 + unittest(!of_overlay_notifier_unregister(&of_nb), 2924 + "of_overlay_notifier_unregister() failed, ret = %d\n", ret); 2925 + } 2926 + 2744 2927 static void __init of_unittest_overlay(void) 2745 2928 { 2746 2929 struct device_node *bus_np = NULL; ··· 2987 2804 2988 2805 of_unittest_remove_tracked_overlays(); 2989 2806 2807 + of_unittest_overlay_notify(); 2808 + 2990 2809 out: 2991 2810 of_node_put(bus_np); 2992 2811 } ··· 3040 2855 OVERLAY_INFO_EXTERN(overlay_12); 3041 2856 OVERLAY_INFO_EXTERN(overlay_13); 3042 2857 OVERLAY_INFO_EXTERN(overlay_15); 2858 + OVERLAY_INFO_EXTERN(overlay_16); 2859 + OVERLAY_INFO_EXTERN(overlay_17); 2860 + OVERLAY_INFO_EXTERN(overlay_18); 2861 + OVERLAY_INFO_EXTERN(overlay_19); 2862 + OVERLAY_INFO_EXTERN(overlay_20); 3043 2863 OVERLAY_INFO_EXTERN(overlay_gpio_01); 3044 2864 OVERLAY_INFO_EXTERN(overlay_gpio_02a); 3045 2865 OVERLAY_INFO_EXTERN(overlay_gpio_02b); ··· 3075 2885 OVERLAY_INFO(overlay_12, 0), 3076 2886 OVERLAY_INFO(overlay_13, 0), 3077 2887 OVERLAY_INFO(overlay_15, 0), 2888 + OVERLAY_INFO(overlay_16, -EBUSY), 2889 + OVERLAY_INFO(overlay_17, -EEXIST), 2890 + OVERLAY_INFO(overlay_18, 0), 2891 + OVERLAY_INFO(overlay_19, 0), 2892 + OVERLAY_INFO(overlay_20, 0), 3078 2893 OVERLAY_INFO(overlay_gpio_01, 0), 3079 2894 OVERLAY_INFO(overlay_gpio_02a, 0), 3080 2895 OVERLAY_INFO(overlay_gpio_02b, 0),