@@ -699,6 +699,10 @@ struct devlink_region {
699699 const struct devlink_region_ops * ops ;
700700 const struct devlink_port_region_ops * port_ops ;
701701 };
702+ struct mutex snapshot_lock ; /* protects snapshot_list,
703+ * max_snapshots and cur_snapshots
704+ * consistency.
705+ */
702706 struct list_head snapshot_list ;
703707 u32 max_snapshots ;
704708 u32 cur_snapshots ;
@@ -6021,7 +6025,7 @@ static int __devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
60216025 * Multiple snapshots can be created on a region.
60226026 * The @snapshot_id should be obtained using the getter function.
60236027 *
6024- * Must be called only while holding the devlink instance lock.
6028+ * Must be called only while holding the region snapshot lock.
60256029 *
60266030 * @region: devlink region of the snapshot
60276031 * @data: snapshot data
@@ -6035,7 +6039,7 @@ __devlink_region_snapshot_create(struct devlink_region *region,
60356039 struct devlink_snapshot * snapshot ;
60366040 int err ;
60376041
6038- devl_assert_locked ( devlink );
6042+ lockdep_assert_held ( & region -> snapshot_lock );
60396043
60406044 /* check if region can hold one more snapshot */
60416045 if (region -> cur_snapshots == region -> max_snapshots )
@@ -6073,7 +6077,7 @@ static void devlink_region_snapshot_del(struct devlink_region *region,
60736077{
60746078 struct devlink * devlink = region -> devlink ;
60756079
6076- devl_assert_locked ( devlink );
6080+ lockdep_assert_held ( & region -> snapshot_lock );
60776081
60786082 devlink_nl_region_notify (region , snapshot , DEVLINK_CMD_REGION_DEL );
60796083 region -> cur_snapshots -- ;
@@ -6252,11 +6256,15 @@ static int devlink_nl_cmd_region_del(struct sk_buff *skb,
62526256 if (!region )
62536257 return - EINVAL ;
62546258
6259+ mutex_lock (& region -> snapshot_lock );
62556260 snapshot = devlink_region_snapshot_get_by_id (region , snapshot_id );
6256- if (!snapshot )
6261+ if (!snapshot ) {
6262+ mutex_unlock (& region -> snapshot_lock );
62576263 return - EINVAL ;
6264+ }
62586265
62596266 devlink_region_snapshot_del (region , snapshot );
6267+ mutex_unlock (& region -> snapshot_lock );
62606268 return 0 ;
62616269}
62626270
@@ -6304,9 +6312,12 @@ devlink_nl_cmd_region_new(struct sk_buff *skb, struct genl_info *info)
63046312 return - EOPNOTSUPP ;
63056313 }
63066314
6315+ mutex_lock (& region -> snapshot_lock );
6316+
63076317 if (region -> cur_snapshots == region -> max_snapshots ) {
63086318 NL_SET_ERR_MSG_MOD (info -> extack , "The region has reached the maximum number of stored snapshots" );
6309- return - ENOSPC ;
6319+ err = - ENOSPC ;
6320+ goto unlock ;
63106321 }
63116322
63126323 snapshot_id_attr = info -> attrs [DEVLINK_ATTR_REGION_SNAPSHOT_ID ];
@@ -6315,17 +6326,18 @@ devlink_nl_cmd_region_new(struct sk_buff *skb, struct genl_info *info)
63156326
63166327 if (devlink_region_snapshot_get_by_id (region , snapshot_id )) {
63176328 NL_SET_ERR_MSG_MOD (info -> extack , "The requested snapshot id is already in use" );
6318- return - EEXIST ;
6329+ err = - EEXIST ;
6330+ goto unlock ;
63196331 }
63206332
63216333 err = __devlink_snapshot_id_insert (devlink , snapshot_id );
63226334 if (err )
6323- return err ;
6335+ goto unlock ;
63246336 } else {
63256337 err = __devlink_region_snapshot_id_get (devlink , & snapshot_id );
63266338 if (err ) {
63276339 NL_SET_ERR_MSG_MOD (info -> extack , "Failed to allocate a new snapshot id" );
6328- return err ;
6340+ goto unlock ;
63296341 }
63306342 }
63316343
@@ -6363,16 +6375,20 @@ devlink_nl_cmd_region_new(struct sk_buff *skb, struct genl_info *info)
63636375 goto err_notify ;
63646376 }
63656377
6378+ mutex_unlock (& region -> snapshot_lock );
63666379 return 0 ;
63676380
63686381err_snapshot_create :
63696382 region -> ops -> destructor (data );
63706383err_snapshot_capture :
63716384 __devlink_snapshot_id_decrement (devlink , snapshot_id );
6385+ mutex_unlock (& region -> snapshot_lock );
63726386 return err ;
63736387
63746388err_notify :
63756389 devlink_region_snapshot_del (region , snapshot );
6390+ unlock :
6391+ mutex_unlock (& region -> snapshot_lock );
63766392 return err ;
63776393}
63786394
@@ -11310,6 +11326,7 @@ struct devlink_region *devl_region_create(struct devlink *devlink,
1131011326 region -> ops = ops ;
1131111327 region -> size = region_size ;
1131211328 INIT_LIST_HEAD (& region -> snapshot_list );
11329+ mutex_init (& region -> snapshot_lock );
1131311330 list_add_tail (& region -> list , & devlink -> region_list );
1131411331 devlink_nl_region_notify (region , NULL , DEVLINK_CMD_REGION_NEW );
1131511332
@@ -11383,6 +11400,7 @@ devlink_port_region_create(struct devlink_port *port,
1138311400 region -> port_ops = ops ;
1138411401 region -> size = region_size ;
1138511402 INIT_LIST_HEAD (& region -> snapshot_list );
11403+ mutex_init (& region -> snapshot_lock );
1138611404 list_add_tail (& region -> list , & port -> region_list );
1138711405 devlink_nl_region_notify (region , NULL , DEVLINK_CMD_REGION_NEW );
1138811406
@@ -11412,6 +11430,7 @@ void devl_region_destroy(struct devlink_region *region)
1141211430 devlink_region_snapshot_del (region , snapshot );
1141311431
1141411432 list_del (& region -> list );
11433+ mutex_destroy (& region -> snapshot_lock );
1141511434
1141611435 devlink_nl_region_notify (region , NULL , DEVLINK_CMD_REGION_DEL );
1141711436 kfree (region );
@@ -11487,13 +11506,11 @@ EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_put);
1148711506int devlink_region_snapshot_create (struct devlink_region * region ,
1148811507 u8 * data , u32 snapshot_id )
1148911508{
11490- struct devlink * devlink = region -> devlink ;
1149111509 int err ;
1149211510
11493- devl_lock ( devlink );
11511+ mutex_lock ( & region -> snapshot_lock );
1149411512 err = __devlink_region_snapshot_create (region , data , snapshot_id );
11495- devl_unlock (devlink );
11496-
11513+ mutex_unlock (& region -> snapshot_lock );
1149711514 return err ;
1149811515}
1149911516EXPORT_SYMBOL_GPL (devlink_region_snapshot_create );
0 commit comments