1 #include <linux/init.h>
3 #include <linux/module.h>
4 #include <linux/mutex.h>
5 #include <linux/slab.h>
9 #include "connection.h"
22 * kdbus_reply_new() - Allocate and set up a new kdbus_reply object
23 * @reply_src: The connection a reply is expected from
24 * @reply_dst: The connection this reply object belongs to
25 * @msg: Message associated with the reply
26 * @name_entry: Name entry used to send the message
27 * @sync: Whether or not to make this reply synchronous
29 * Allocate and fill a new kdbus_reply object.
31 * Return: New kdbus_conn object on success, ERR_PTR on error.
33 struct kdbus_reply *kdbus_reply_new(struct kdbus_conn *reply_src,
34 struct kdbus_conn *reply_dst,
35 const struct kdbus_msg *msg,
36 struct kdbus_name_entry *name_entry,
39 struct kdbus_reply *r;
42 if (atomic_inc_return(&reply_dst->request_count) >
43 KDBUS_CONN_MAX_REQUESTS_PENDING) {
45 goto exit_dec_request_count;
48 r = kzalloc(sizeof(*r), GFP_KERNEL);
51 goto exit_dec_request_count;
55 INIT_LIST_HEAD(&r->entry);
56 r->reply_src = kdbus_conn_ref(reply_src);
57 r->reply_dst = kdbus_conn_ref(reply_dst);
58 r->cookie = msg->cookie;
59 r->name_id = name_entry ? name_entry->name_id : 0;
60 r->deadline_ns = msg->timeout_ns;
69 exit_dec_request_count:
70 atomic_dec(&reply_dst->request_count);
74 static void __kdbus_reply_free(struct kref *kref)
76 struct kdbus_reply *reply =
77 container_of(kref, struct kdbus_reply, kref);
79 atomic_dec(&reply->reply_dst->request_count);
80 kdbus_conn_unref(reply->reply_src);
81 kdbus_conn_unref(reply->reply_dst);
86 * kdbus_reply_ref() - Increase reference on kdbus_reply
87 * @r: The reply, may be %NULL
89 * Return: The reply object with an extra reference
91 struct kdbus_reply *kdbus_reply_ref(struct kdbus_reply *r)
99 * kdbus_reply_unref() - Decrease reference on kdbus_reply
100 * @r: The reply, may be %NULL
104 struct kdbus_reply *kdbus_reply_unref(struct kdbus_reply *r)
107 kref_put(&r->kref, __kdbus_reply_free);
112 * kdbus_reply_link() - Link reply object into target connection
115 void kdbus_reply_link(struct kdbus_reply *r)
117 if (WARN_ON(!list_empty(&r->entry)))
120 list_add_tail(&r->entry, &r->reply_dst->reply_list);
125 * kdbus_reply_unlink() - Unlink reply object from target connection
126 * @r: Reply to unlink
128 void kdbus_reply_unlink(struct kdbus_reply *r)
130 if (!list_empty(&r->entry)) {
131 list_del_init(&r->entry);
132 kdbus_reply_unref(r);
137 * kdbus_sync_reply_wakeup() - Wake a synchronously blocking reply
138 * @reply: The reply object
139 * @err: Error code to set on the remote side
141 * Wake up remote peer (method origin) with the appropriate synchronous reply
144 void kdbus_sync_reply_wakeup(struct kdbus_reply *reply, int err)
146 if (WARN_ON(!reply->sync))
149 reply->waiting = false;
151 wake_up_interruptible(&reply->reply_dst->wait);
155 * kdbus_reply_find() - Find the corresponding reply object
156 * @replying: The replying connection or NULL
157 * @reply_dst: The connection the reply will be sent to
159 * @cookie: The cookie of the requesting message
161 * Lookup a reply object that should be sent as a reply by
162 * @replying to @reply_dst with the given cookie.
164 * Callers must take the @reply_dst lock.
166 * Return: the corresponding reply object or NULL if not found
168 struct kdbus_reply *kdbus_reply_find(struct kdbus_conn *replying,
169 struct kdbus_conn *reply_dst,
172 struct kdbus_reply *r;
174 list_for_each_entry(r, &reply_dst->reply_list, entry) {
175 if (r->cookie == cookie &&
176 (!replying || r->reply_src == replying))
184 * kdbus_reply_list_scan_work() - Worker callback to scan the replies of a
185 * connection for exceeded timeouts
186 * @work: Work struct of the connection to scan
188 * Walk the list of replies stored with a connection and look for entries
189 * that have exceeded their timeout. If such an entry is found, a timeout
190 * notification is sent to the waiting peer, and the reply is removed from
193 * The work is rescheduled to the nearest timeout found during the list
196 void kdbus_reply_list_scan_work(struct work_struct *work)
198 struct kdbus_conn *conn =
199 container_of(work, struct kdbus_conn, work.work);
200 struct kdbus_reply *reply, *reply_tmp;
201 u64 deadline = ~0ULL;
204 now = ktime_get_ns();
206 mutex_lock(&conn->lock);
207 if (!kdbus_conn_active(conn)) {
208 mutex_unlock(&conn->lock);
212 list_for_each_entry_safe(reply, reply_tmp, &conn->reply_list, entry) {
214 * If the reply block is waiting for synchronous I/O,
215 * the timeout is handled by wait_event_*_timeout(),
216 * so we don't have to care for it here.
218 if (reply->sync && !reply->interrupted)
221 WARN_ON(reply->reply_dst != conn);
223 if (reply->deadline_ns > now) {
224 /* remember next timeout */
225 if (deadline > reply->deadline_ns)
226 deadline = reply->deadline_ns;
232 * A zero deadline means the connection died, was
233 * cleaned up already and the notification was sent.
234 * Don't send notifications for reply trackers that were
235 * left in an interrupted syscall state.
237 if (reply->deadline_ns != 0 && !reply->interrupted)
238 kdbus_notify_reply_timeout(conn->ep->bus, conn->id,
241 kdbus_reply_unlink(reply);
244 /* rearm delayed work with next timeout */
245 if (deadline != ~0ULL)
246 schedule_delayed_work(&conn->work,
247 nsecs_to_jiffies(deadline - now));
249 mutex_unlock(&conn->lock);
251 kdbus_notify_flush(conn->ep->bus);