@@ -784,6 +784,49 @@ struct napi_struct *netdev_napi_by_id(struct net *net, unsigned int napi_id)
784
784
return napi ;
785
785
}
786
786
787
+ /**
788
+ * netdev_napi_by_id_lock() - find a device by NAPI ID and lock it
789
+ * @net: the applicable net namespace
790
+ * @napi_id: ID of a NAPI of a target device
791
+ *
792
+ * Find a NAPI instance with @napi_id. Lock its device.
793
+ * The device must be in %NETREG_REGISTERED state for lookup to succeed.
794
+ * netdev_unlock() must be called to release it.
795
+ *
796
+ * Return: pointer to NAPI, its device with lock held, NULL if not found.
797
+ */
798
+ struct napi_struct *
799
+ netdev_napi_by_id_lock (struct net * net , unsigned int napi_id )
800
+ {
801
+ struct napi_struct * napi ;
802
+ struct net_device * dev ;
803
+
804
+ rcu_read_lock ();
805
+ napi = netdev_napi_by_id (net , napi_id );
806
+ if (!napi || READ_ONCE (napi -> dev -> reg_state ) != NETREG_REGISTERED ) {
807
+ rcu_read_unlock ();
808
+ return NULL ;
809
+ }
810
+
811
+ dev = napi -> dev ;
812
+ dev_hold (dev );
813
+ rcu_read_unlock ();
814
+
815
+ dev = __netdev_put_lock (dev );
816
+ if (!dev )
817
+ return NULL ;
818
+
819
+ rcu_read_lock ();
820
+ napi = netdev_napi_by_id (net , napi_id );
821
+ if (napi && napi -> dev != dev )
822
+ napi = NULL ;
823
+ rcu_read_unlock ();
824
+
825
+ if (!napi )
826
+ netdev_unlock (dev );
827
+ return napi ;
828
+ }
829
+
787
830
/**
788
831
* __dev_get_by_name - find a device by its name
789
832
* @net: the applicable net namespace
@@ -972,6 +1015,73 @@ struct net_device *dev_get_by_napi_id(unsigned int napi_id)
972
1015
return napi ? napi -> dev : NULL ;
973
1016
}
974
1017
1018
+ /* Release the held reference on the net_device, and if the net_device
1019
+ * is still registered try to lock the instance lock. If device is being
1020
+ * unregistered NULL will be returned (but the reference has been released,
1021
+ * either way!)
1022
+ *
1023
+ * This helper is intended for locking net_device after it has been looked up
1024
+ * using a lockless lookup helper. Lock prevents the instance from going away.
1025
+ */
1026
+ struct net_device * __netdev_put_lock (struct net_device * dev )
1027
+ {
1028
+ netdev_lock (dev );
1029
+ if (dev -> reg_state > NETREG_REGISTERED ) {
1030
+ netdev_unlock (dev );
1031
+ dev_put (dev );
1032
+ return NULL ;
1033
+ }
1034
+ dev_put (dev );
1035
+ return dev ;
1036
+ }
1037
+
1038
+ /**
1039
+ * netdev_get_by_index_lock() - find a device by its ifindex
1040
+ * @net: the applicable net namespace
1041
+ * @ifindex: index of device
1042
+ *
1043
+ * Search for an interface by index. If a valid device
1044
+ * with @ifindex is found it will be returned with netdev->lock held.
1045
+ * netdev_unlock() must be called to release it.
1046
+ *
1047
+ * Return: pointer to a device with lock held, NULL if not found.
1048
+ */
1049
+ struct net_device * netdev_get_by_index_lock (struct net * net , int ifindex )
1050
+ {
1051
+ struct net_device * dev ;
1052
+
1053
+ dev = dev_get_by_index (net , ifindex );
1054
+ if (!dev )
1055
+ return NULL ;
1056
+
1057
+ return __netdev_put_lock (dev );
1058
+ }
1059
+
1060
+ struct net_device *
1061
+ netdev_xa_find_lock (struct net * net , struct net_device * dev ,
1062
+ unsigned long * index )
1063
+ {
1064
+ if (dev )
1065
+ netdev_unlock (dev );
1066
+
1067
+ do {
1068
+ rcu_read_lock ();
1069
+ dev = xa_find (& net -> dev_by_index , index , ULONG_MAX , XA_PRESENT );
1070
+ if (!dev ) {
1071
+ rcu_read_unlock ();
1072
+ return NULL ;
1073
+ }
1074
+ dev_hold (dev );
1075
+ rcu_read_unlock ();
1076
+
1077
+ dev = __netdev_put_lock (dev );
1078
+ if (dev )
1079
+ return dev ;
1080
+
1081
+ (* index )++ ;
1082
+ } while (true);
1083
+ }
1084
+
975
1085
static DEFINE_SEQLOCK (netdev_rename_lock );
976
1086
977
1087
void netdev_copy_name (struct net_device * dev , char * name )
0 commit comments