/**
* struct kdbus_conn_reply - an entry of kdbus_conn's list of replies
+ * @kref: Ref-count of this object
* @entry: The entry of the connection's reply_list
* @reply_dst: The connection the reply will be sent to (method origin)
* @queue_entry: The queue enty item that is prepared by the replying
* @err: The error code for the synchronous reply
*/
struct kdbus_conn_reply {
+ struct kref kref;
struct list_head entry;
struct kdbus_conn *reply_dst;
struct kdbus_queue_entry *queue_entry;
goto exit_dec_reply_count;
}
+ kref_init(&r->kref);
r->reply_dst = kdbus_conn_ref(reply_dst);
r->cookie = msg->cookie;
r->name_id = name_entry ? name_entry->name_id : 0;
return ret;
}
-static void kdbus_conn_reply_free(struct kdbus_conn_reply *reply)
+static void __kdbus_conn_reply_free(struct kref *kref)
{
+ struct kdbus_conn_reply *reply = container_of(kref,
+ struct kdbus_conn_reply,
+ kref);
+
atomic_dec(&reply->reply_dst->reply_count);
kdbus_conn_unref(reply->reply_dst);
kfree(reply);
}
+static struct kdbus_conn_reply*
+kdbus_conn_reply_ref(struct kdbus_conn_reply *r)
+{
+ if (r)
+ kref_get(&r->kref);
+ return r;
+}
+
+static struct kdbus_conn_reply*
+kdbus_conn_reply_unref(struct kdbus_conn_reply *r)
+{
+ if (r)
+ kref_put(&r->kref, __kdbus_conn_reply_free);
+ return NULL;
+}
+
static void kdbus_conn_reply_sync(struct kdbus_conn_reply *reply, int err)
{
BUG_ON(!reply->sync);
reply->cookie);
list_del_init(&reply->entry);
- kdbus_conn_reply_free(reply);
+ kdbus_conn_reply_unref(reply);
}
/* rearm delayed work with next timeout */
kdbus_conn_reply_sync(entry->reply, -EPIPE);
} else {
list_del_init(&entry->reply->entry);
- kdbus_conn_reply_free(entry->reply);
+ kdbus_conn_reply_unref(entry->reply);
kdbus_notify_reply_dead(conn->bus,
entry->src_id,
entry->cookie);
*reply_wake = r;
} else {
list_del_init(&r->entry);
- kdbus_conn_reply_free(r);
+ kdbus_conn_reply_unref(r);
}
allowed = true;
}
mutex_unlock(&conn_src->lock);
- kdbus_conn_reply_free(reply_wait);
+ kdbus_conn_reply_unref(reply_wait);
return ret;
}
kmsg, reply_wait);
if (ret < 0) {
if (reply_wait)
- kdbus_conn_reply_free(reply_wait);
+ kdbus_conn_reply_unref(reply_wait);
goto exit_unref;
}
}
reply->cookie);
list_del(&reply->entry);
- kdbus_conn_reply_free(reply);
+ kdbus_conn_reply_unref(reply);
}
kdbus_notify_id_change(conn->bus, KDBUS_ITEM_ID_REMOVE,
list_for_each_entry_safe(q, q_tmp, &msg_list, entry)
kdbus_queue_entry_free(q);
list_for_each_entry_safe(r, r_tmp, &reply_list, entry)
- kdbus_conn_reply_free(r);
+ kdbus_conn_reply_unref(r);
return -ECONNRESET;
}