Skip to content

Commit 2dec18a

Browse files
Jiri Pirkokuba-moo
authored andcommitted
net: devlink: remove region snapshots list dependency on devlink->lock
After mlx4 driver is converted to do locked reload, devlink_region_snapshot_create() may be called from both locked and unlocked context. Note that in mlx4 region snapshots could be created on any command failure. That can happen in any flow that involves commands to FW, which means most of the driver flows. So resolve this by removing dependency on devlink->lock for region snapshots list consistency and introduce new mutex to ensure it. Signed-off-by: Jiri Pirko <jiri@nvidia.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 5502e87 commit 2dec18a

File tree

1 file changed

+29
-12
lines changed

1 file changed

+29
-12
lines changed

net/core/devlink.c

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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

63686381
err_snapshot_create:
63696382
region->ops->destructor(data);
63706383
err_snapshot_capture:
63716384
__devlink_snapshot_id_decrement(devlink, snapshot_id);
6385+
mutex_unlock(&region->snapshot_lock);
63726386
return err;
63736387

63746388
err_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);
1148711506
int 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
}
1149911516
EXPORT_SYMBOL_GPL(devlink_region_snapshot_create);

0 commit comments

Comments
 (0)