@@ -36,24 +36,6 @@ static struct net_shaper_binding *net_shaper_binding_from_ctx(void *ctx)
3636 return & ((struct net_shaper_nl_ctx * )ctx )-> binding ;
3737}
3838
39- static void net_shaper_lock (struct net_shaper_binding * binding )
40- {
41- switch (binding -> type ) {
42- case NET_SHAPER_BINDING_TYPE_NETDEV :
43- netdev_lock (binding -> netdev );
44- break ;
45- }
46- }
47-
48- static void net_shaper_unlock (struct net_shaper_binding * binding )
49- {
50- switch (binding -> type ) {
51- case NET_SHAPER_BINDING_TYPE_NETDEV :
52- netdev_unlock (binding -> netdev );
53- break ;
54- }
55- }
56-
5739static struct net_shaper_hierarchy *
5840net_shaper_hierarchy (struct net_shaper_binding * binding )
5941{
@@ -219,12 +201,49 @@ static int net_shaper_ctx_setup(const struct genl_info *info, int type,
219201 return 0 ;
220202}
221203
204+ /* Like net_shaper_ctx_setup(), but for "write" handlers (never for dumps!)
205+ * Acquires the lock protecting the hierarchy (instance lock for netdev).
206+ */
207+ static int net_shaper_ctx_setup_lock (const struct genl_info * info , int type ,
208+ struct net_shaper_nl_ctx * ctx )
209+ {
210+ struct net * ns = genl_info_net (info );
211+ struct net_device * dev ;
212+ int ifindex ;
213+
214+ if (GENL_REQ_ATTR_CHECK (info , type ))
215+ return - EINVAL ;
216+
217+ ifindex = nla_get_u32 (info -> attrs [type ]);
218+ dev = netdev_get_by_index_lock (ns , ifindex );
219+ if (!dev ) {
220+ NL_SET_BAD_ATTR (info -> extack , info -> attrs [type ]);
221+ return - ENOENT ;
222+ }
223+
224+ if (!dev -> netdev_ops -> net_shaper_ops ) {
225+ NL_SET_BAD_ATTR (info -> extack , info -> attrs [type ]);
226+ netdev_unlock (dev );
227+ return - EOPNOTSUPP ;
228+ }
229+
230+ ctx -> binding .type = NET_SHAPER_BINDING_TYPE_NETDEV ;
231+ ctx -> binding .netdev = dev ;
232+ return 0 ;
233+ }
234+
222235static void net_shaper_ctx_cleanup (struct net_shaper_nl_ctx * ctx )
223236{
224237 if (ctx -> binding .type == NET_SHAPER_BINDING_TYPE_NETDEV )
225238 netdev_put (ctx -> binding .netdev , & ctx -> dev_tracker );
226239}
227240
241+ static void net_shaper_ctx_cleanup_unlock (struct net_shaper_nl_ctx * ctx )
242+ {
243+ if (ctx -> binding .type == NET_SHAPER_BINDING_TYPE_NETDEV )
244+ netdev_unlock (ctx -> binding .netdev );
245+ }
246+
228247static u32 net_shaper_handle_to_index (const struct net_shaper_handle * handle )
229248{
230249 return FIELD_PREP (NET_SHAPER_SCOPE_MASK , handle -> scope ) |
@@ -278,7 +297,7 @@ net_shaper_lookup(struct net_shaper_binding *binding,
278297}
279298
280299/* Allocate on demand the per device shaper's hierarchy container.
281- * Called under the net shaper lock
300+ * Called under the lock protecting the hierarchy (instance lock for netdev)
282301 */
283302static struct net_shaper_hierarchy *
284303net_shaper_hierarchy_setup (struct net_shaper_binding * binding )
@@ -697,6 +716,22 @@ void net_shaper_nl_post_doit(const struct genl_split_ops *ops,
697716 net_shaper_generic_post (info );
698717}
699718
719+ int net_shaper_nl_pre_doit_write (const struct genl_split_ops * ops ,
720+ struct sk_buff * skb , struct genl_info * info )
721+ {
722+ struct net_shaper_nl_ctx * ctx = (struct net_shaper_nl_ctx * )info -> ctx ;
723+
724+ BUILD_BUG_ON (sizeof (* ctx ) > sizeof (info -> ctx ));
725+
726+ return net_shaper_ctx_setup_lock (info , NET_SHAPER_A_IFINDEX , ctx );
727+ }
728+
729+ void net_shaper_nl_post_doit_write (const struct genl_split_ops * ops ,
730+ struct sk_buff * skb , struct genl_info * info )
731+ {
732+ net_shaper_ctx_cleanup_unlock ((struct net_shaper_nl_ctx * )info -> ctx );
733+ }
734+
700735int net_shaper_nl_pre_dumpit (struct netlink_callback * cb )
701736{
702737 struct net_shaper_nl_ctx * ctx = (struct net_shaper_nl_ctx * )cb -> ctx ;
@@ -824,45 +859,38 @@ int net_shaper_nl_set_doit(struct sk_buff *skb, struct genl_info *info)
824859
825860 binding = net_shaper_binding_from_ctx (info -> ctx );
826861
827- net_shaper_lock (binding );
828862 ret = net_shaper_parse_info (binding , info -> attrs , info , & shaper ,
829863 & exists );
830864 if (ret )
831- goto unlock ;
865+ return ret ;
832866
833867 if (!exists )
834868 net_shaper_default_parent (& shaper .handle , & shaper .parent );
835869
836870 hierarchy = net_shaper_hierarchy_setup (binding );
837- if (!hierarchy ) {
838- ret = - ENOMEM ;
839- goto unlock ;
840- }
871+ if (!hierarchy )
872+ return - ENOMEM ;
841873
842874 /* The 'set' operation can't create node-scope shapers. */
843875 handle = shaper .handle ;
844876 if (handle .scope == NET_SHAPER_SCOPE_NODE &&
845- !net_shaper_lookup (binding , & handle )) {
846- ret = - ENOENT ;
847- goto unlock ;
848- }
877+ !net_shaper_lookup (binding , & handle ))
878+ return - ENOENT ;
849879
850880 ret = net_shaper_pre_insert (binding , & handle , info -> extack );
851881 if (ret )
852- goto unlock ;
882+ return ret ;
853883
854884 ops = net_shaper_ops (binding );
855885 ret = ops -> set (binding , & shaper , info -> extack );
856886 if (ret ) {
857887 net_shaper_rollback (binding );
858- goto unlock ;
888+ return ret ;
859889 }
860890
861891 net_shaper_commit (binding , 1 , & shaper );
862892
863- unlock :
864- net_shaper_unlock (binding );
865- return ret ;
893+ return 0 ;
866894}
867895
868896static int __net_shaper_delete (struct net_shaper_binding * binding ,
@@ -1090,35 +1118,26 @@ int net_shaper_nl_delete_doit(struct sk_buff *skb, struct genl_info *info)
10901118
10911119 binding = net_shaper_binding_from_ctx (info -> ctx );
10921120
1093- net_shaper_lock (binding );
10941121 ret = net_shaper_parse_handle (info -> attrs [NET_SHAPER_A_HANDLE ], info ,
10951122 & handle );
10961123 if (ret )
1097- goto unlock ;
1124+ return ret ;
10981125
10991126 hierarchy = net_shaper_hierarchy (binding );
1100- if (!hierarchy ) {
1101- ret = - ENOENT ;
1102- goto unlock ;
1103- }
1127+ if (!hierarchy )
1128+ return - ENOENT ;
11041129
11051130 shaper = net_shaper_lookup (binding , & handle );
1106- if (!shaper ) {
1107- ret = - ENOENT ;
1108- goto unlock ;
1109- }
1131+ if (!shaper )
1132+ return - ENOENT ;
11101133
11111134 if (handle .scope == NET_SHAPER_SCOPE_NODE ) {
11121135 ret = net_shaper_pre_del_node (binding , shaper , info -> extack );
11131136 if (ret )
1114- goto unlock ;
1137+ return ret ;
11151138 }
11161139
1117- ret = __net_shaper_delete (binding , shaper , info -> extack );
1118-
1119- unlock :
1120- net_shaper_unlock (binding );
1121- return ret ;
1140+ return __net_shaper_delete (binding , shaper , info -> extack );
11221141}
11231142
11241143static int net_shaper_group_send_reply (struct net_shaper_binding * binding ,
@@ -1167,21 +1186,17 @@ int net_shaper_nl_group_doit(struct sk_buff *skb, struct genl_info *info)
11671186 if (!net_shaper_ops (binding )-> group )
11681187 return - EOPNOTSUPP ;
11691188
1170- net_shaper_lock (binding );
11711189 leaves_count = net_shaper_list_len (info , NET_SHAPER_A_LEAVES );
11721190 if (!leaves_count ) {
11731191 NL_SET_BAD_ATTR (info -> extack ,
11741192 info -> attrs [NET_SHAPER_A_LEAVES ]);
1175- ret = - EINVAL ;
1176- goto unlock ;
1193+ return - EINVAL ;
11771194 }
11781195
11791196 leaves = kcalloc (leaves_count , sizeof (struct net_shaper ) +
11801197 sizeof (struct net_shaper * ), GFP_KERNEL );
1181- if (!leaves ) {
1182- ret = - ENOMEM ;
1183- goto unlock ;
1184- }
1198+ if (!leaves )
1199+ return - ENOMEM ;
11851200 old_nodes = (void * )& leaves [leaves_count ];
11861201
11871202 ret = net_shaper_parse_node (binding , info -> attrs , info , & node );
@@ -1258,9 +1273,6 @@ int net_shaper_nl_group_doit(struct sk_buff *skb, struct genl_info *info)
12581273
12591274free_leaves :
12601275 kfree (leaves );
1261-
1262- unlock :
1263- net_shaper_unlock (binding );
12641276 return ret ;
12651277
12661278free_msg :
@@ -1370,14 +1382,12 @@ static void net_shaper_flush(struct net_shaper_binding *binding)
13701382 if (!hierarchy )
13711383 return ;
13721384
1373- net_shaper_lock (binding );
13741385 xa_lock (& hierarchy -> shapers );
13751386 xa_for_each (& hierarchy -> shapers , index , cur ) {
13761387 __xa_erase (& hierarchy -> shapers , index );
13771388 kfree (cur );
13781389 }
13791390 xa_unlock (& hierarchy -> shapers );
1380- net_shaper_unlock (binding );
13811391
13821392 kfree (hierarchy );
13831393}
0 commit comments