static int gb_operation_response_send(struct gb_operation *operation,
int errno);
+/* Caller holds operation reference. */
+static inline void gb_operation_get_active(struct gb_operation *operation)
+{
+ atomic_inc(&operation->active);
+}
+
+/* Caller holds operation reference. */
+static inline void gb_operation_put_active(struct gb_operation *operation)
+{
+ atomic_dec(&operation->active);
+}
+
/*
* Set an operation's result.
*
operation->callback(operation);
+ gb_operation_put_active(operation);
gb_operation_put(operation);
}
INIT_WORK(&operation->work, gb_operation_work);
init_completion(&operation->completion);
kref_init(&operation->kref);
+ atomic_set(&operation->active, 0);
spin_lock_irqsave(&gb_operations_lock, flags);
list_add_tail(&operation->links, &connection->operations);
* It'll be dropped when the operation completes.
*/
gb_operation_get(operation);
+ gb_operation_get_active(operation);
/*
* Record the callback function, which is executed in
gb_operation_result_set(operation, -EINPROGRESS);
ret = gb_message_send(operation->request, gfp);
- if (ret)
+ if (ret) {
+ gb_operation_put_active(operation);
gb_operation_put(operation);
+ }
return ret;
}
/* Reference will be dropped when message has been sent. */
gb_operation_get(operation);
+ gb_operation_get_active(operation);
/* Fill in the response header and send it */
operation->response->header->result = gb_operation_errno_map(errno);
ret = gb_message_send(operation->response, GFP_KERNEL);
- if (ret)
+ if (ret) {
+ gb_operation_put_active(operation);
gb_operation_put(operation);
+ }
return ret;
}
dev_err(&operation->connection->dev,
"error sending response: %d\n", status);
}
+ gb_operation_put_active(operation);
gb_operation_put(operation);
} else if (status) {
if (gb_operation_result_set(operation, status))
return; /* XXX Respond with pre-allocated ENOMEM */
}
+ gb_operation_get_active(operation);
+
/*
* Incoming requests are handled by arranging for the
* request handler to be the operation's callback function.
} else {
if (gb_operation_result_set(operation, errno)) {
gb_message_cancel(operation->request);
+ gb_operation_put_active(operation);
gb_operation_put(operation);
}
}