MT#55283 change "del" strategy

Only do deletion if no other refs are open.

Add new "kill" method to override this.

Handle spurious EBUSY in daemon shutdown.

Change-Id: Ic84a0c3c1e3a007052baf19d22d79cbccf12c414
pull/2141/head
Richard Fuchs 4 weeks ago
parent 16f5a4d10e
commit 03c37c893f

@ -56,7 +56,16 @@ static bool kernel_create_table(unsigned int id) {
}
static bool kernel_delete_table(unsigned int id) {
return kernel_action_table("del", id);
for (unsigned int i = 0; i < 5; i++) {
bool ok = kernel_action_table("del", id);
if (ok)
return true;
if (errno != EBUSY)
return false;
usleep(20000);
}
return false;
}
static void kernel_pin_memory(void *b, size_t len) {

@ -1251,7 +1251,6 @@ static void table_put(struct rtpengine_table *t) {
release_shm(&t->shms[i]);
kfree(t->shms);
clear_table_proc_files(t);
#ifdef KERNEL_PLAYER
clear_table_player(t);
#endif
@ -1346,12 +1345,42 @@ static void call_put(struct re_call *call) {
static int unlink_table(struct rtpengine_table *t) {
unsigned long flags;
struct re_call *call;
if (t->id >= MAX_ID)
DBG("Unlinking table %u\n", t->id);
write_lock_irqsave(&table_lock, flags);
if (t->id >= MAX_ID || rtpe_table[t->id] != t) {
write_unlock_irqrestore(&table_lock, flags);
return -EINVAL;
}
if (t->pid) {
write_unlock_irqrestore(&table_lock, flags);
return -EBUSY;
}
// this ref and the entry in rtpe_table
if (atomic_read(&t->refcnt) != 2) {
write_unlock_irqrestore(&table_lock, flags);
return -EBUSY;
}
rtpe_table[t->id] = NULL;
t->id = -1u;
write_unlock_irqrestore(&table_lock, flags);
table_put(t);
DBG("Unlinking table %u\n", t->id);
// safe to clear, nothing else could be open any more
clear_table_proc_files(t);
// last ref -> free
table_put(t);
return 0;
}
static int kill_table(struct rtpengine_table *t) {
unsigned long flags;
struct re_call *call;
DBG("Killing table %u\n", t->id);
write_lock_irqsave(&table_lock, flags);
if (t->id >= MAX_ID || rtpe_table[t->id] != t) {
@ -1363,8 +1392,9 @@ static int unlink_table(struct rtpengine_table *t) {
return -EBUSY;
}
rtpe_table[t->id] = NULL;
t->id = -1;
t->id = -1u;
write_unlock_irqrestore(&table_lock, flags);
table_put(t);
_w_lock(&calls.lock, flags);
while (!list_empty(&t->calls)) {
@ -1375,7 +1405,10 @@ static int unlink_table(struct rtpengine_table *t) {
}
_w_unlock(&calls.lock, flags);
// *should* be the last ref
clear_table_proc_files(t);
// last ref -> free
table_put(t);
return 0;
@ -1383,7 +1416,6 @@ static int unlink_table(struct rtpengine_table *t) {
static struct rtpengine_table *get_table(unsigned int id) {
struct rtpengine_table *t;
unsigned long flags;
@ -3066,7 +3098,20 @@ static ssize_t proc_main_control_write(struct file *file, const char __user *buf
if (!t)
return -ENOENT;
err = unlink_table(t);
table_put(t);
t = NULL;
if (err)
return err;
}
else if (!strncmp(b, "kill ", 5)) {
id = simple_strtoul(b + 5, &endp, 10);
if (endp == b + 5)
return -EINVAL;
if (id >= MAX_ID)
return -EINVAL;
t = get_table((uint32_t) id);
if (!t)
return -ENOENT;
err = kill_table(t);
t = NULL;
if (err)
return err;

Loading…
Cancel
Save