Skip to content

Commit 84fe1eb

Browse files
committed
ipmi:msghandler: Fix locking around users and interfaces
Now that SRCU is gone from IPMI, it can no longer be sloppy about locking. Use the users mutex now when sending a message, not the big ipmi_interfaces mutex, because it can result in a recursive lock. The users mutex will work because the interface destroy code claims it after setting the interface in shutdown mode. Also, due to the same changes, rework the refcounting on users and interfaces. Remove the refcount to an interface when the user is freed, not when it is destroyed. If the interface is destroyed while the user still exists, the user will still point to the interface to test that it is valid if the user tries to do anything but delete the user. Signed-off-by: Corey Minyard <[email protected]>
1 parent 83d19f0 commit 84fe1eb

File tree

1 file changed

+25
-26
lines changed

1 file changed

+25
-26
lines changed

drivers/char/ipmi/ipmi_msghandler.c

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ static void handle_new_recv_msgs(struct ipmi_smi *intf);
4646
static void need_waiter(struct ipmi_smi *intf);
4747
static int handle_one_recv_msg(struct ipmi_smi *intf,
4848
struct ipmi_smi_msg *msg);
49+
static void intf_free(struct kref *ref);
4950

5051
static bool initialized;
5152
static bool drvregistered;
@@ -196,25 +197,6 @@ struct ipmi_user {
196197
atomic_t nr_msgs;
197198
};
198199

199-
static void free_ipmi_user(struct kref *ref)
200-
{
201-
struct ipmi_user *user = container_of(ref, struct ipmi_user, refcount);
202-
203-
vfree(user);
204-
}
205-
206-
static void release_ipmi_user(struct ipmi_user *user)
207-
{
208-
kref_put(&user->refcount, free_ipmi_user);
209-
}
210-
211-
static struct ipmi_user *acquire_ipmi_user(struct ipmi_user *user)
212-
{
213-
if (!kref_get_unless_zero(&user->refcount))
214-
return NULL;
215-
return user;
216-
}
217-
218200
struct cmd_rcvr {
219201
struct list_head link;
220202

@@ -611,6 +593,28 @@ static int __ipmi_bmc_register(struct ipmi_smi *intf,
611593
bool guid_set, guid_t *guid, int intf_num);
612594
static int __scan_channels(struct ipmi_smi *intf, struct ipmi_device_id *id);
613595

596+
static void free_ipmi_user(struct kref *ref)
597+
{
598+
struct ipmi_user *user = container_of(ref, struct ipmi_user, refcount);
599+
struct module *owner;
600+
601+
owner = user->intf->owner;
602+
kref_put(&user->intf->refcount, intf_free);
603+
module_put(owner);
604+
vfree(user);
605+
}
606+
607+
static void release_ipmi_user(struct ipmi_user *user)
608+
{
609+
kref_put(&user->refcount, free_ipmi_user);
610+
}
611+
612+
static struct ipmi_user *acquire_ipmi_user(struct ipmi_user *user)
613+
{
614+
if (!kref_get_unless_zero(&user->refcount))
615+
return NULL;
616+
return user;
617+
}
614618

615619
/*
616620
* The driver model view of the IPMI messaging driver.
@@ -1330,7 +1334,6 @@ static void _ipmi_destroy_user(struct ipmi_user *user)
13301334
unsigned long flags;
13311335
struct cmd_rcvr *rcvr;
13321336
struct cmd_rcvr *rcvrs = NULL;
1333-
struct module *owner;
13341337

13351338
if (!refcount_dec_if_one(&user->destroyed))
13361339
return;
@@ -1382,10 +1385,6 @@ static void _ipmi_destroy_user(struct ipmi_user *user)
13821385
}
13831386

13841387
release_ipmi_user(user);
1385-
1386-
owner = intf->owner;
1387-
kref_put(&intf->refcount, intf_free);
1388-
module_put(owner);
13891388
}
13901389

13911390
void ipmi_destroy_user(struct ipmi_user *user)
@@ -2315,7 +2314,7 @@ static int i_ipmi_request(struct ipmi_user *user,
23152314
}
23162315
}
23172316

2318-
mutex_lock(&ipmi_interfaces_mutex);
2317+
mutex_lock(&intf->users_mutex);
23192318
if (intf->in_shutdown) {
23202319
rv = -ENODEV;
23212320
goto out_err;
@@ -2361,7 +2360,7 @@ static int i_ipmi_request(struct ipmi_user *user,
23612360

23622361
smi_send(intf, intf->handlers, smi_msg, priority);
23632362
}
2364-
mutex_unlock(&ipmi_interfaces_mutex);
2363+
mutex_unlock(&intf->users_mutex);
23652364

23662365
out:
23672366
if (rv && user)

0 commit comments

Comments
 (0)