diff mbox series

tools/oxenstored: port XS_INTRODUCE evtchn rebind function from cxenstored

Message ID 1566240335-6614-1-git-send-email-igor.druzhinin@citrix.com (mailing list archive)
State New, archived
Headers show
Series tools/oxenstored: port XS_INTRODUCE evtchn rebind function from cxenstored | expand

Commit Message

Igor Druzhinin Aug. 19, 2019, 6:45 p.m. UTC
C version of xenstored had this ability since 61aaed0d5 ("Allow
XS_INTRODUCE to be used for rebinding the xenstore evtchn.") from 2007.
Copy it as is to Ocaml version.

Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com>
---
 tools/ocaml/xenstored/domain.ml  | 6 +++++-
 tools/ocaml/xenstored/process.ml | 8 +++++++-
 2 files changed, 12 insertions(+), 2 deletions(-)

Comments

Christian Lindig Aug. 20, 2019, 8:21 a.m. UTC | #1
> +			if (Domain.get_mfn edom) = mfn && (Connections.find_domain cons domid) != con then begin

This should use <> instead of != because != is pointer inequality in OCaml. The parentheses are not strictly necessary because function application has precedence. So:

	if Domain.get_mfn edom = mfn && Connections.find_domain cons domid <> con then begin

— Christian

> On 19 Aug 2019, at 19:45, Igor Druzhinin <igor.druzhinin@citrix.com> wrote:
> 
> C version of xenstored had this ability since 61aaed0d5 ("Allow
> XS_INTRODUCE to be used for rebinding the xenstore evtchn.") from 2007.
> Copy it as is to Ocaml version.
> 
> Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com>
> ---
> tools/ocaml/xenstored/domain.ml  | 6 +++++-
> tools/ocaml/xenstored/process.ml | 8 +++++++-
> 2 files changed, 12 insertions(+), 2 deletions(-)
> 
> diff --git a/tools/ocaml/xenstored/domain.ml b/tools/ocaml/xenstored/domain.ml
> index b0a01b0..aeb185f 100644
> --- a/tools/ocaml/xenstored/domain.ml
> +++ b/tools/ocaml/xenstored/domain.ml
> @@ -23,9 +23,9 @@ type t =
> {
> 	id: Xenctrl.domid;
> 	mfn: nativeint;
> -	remote_port: int;
> 	interface: Xenmmap.mmap_interface;
> 	eventchn: Event.t;
> +	mutable remote_port: int;
> 	mutable port: Xeneventchn.t option;
> 	mutable bad_client: bool;
> 	mutable io_credit: int; (* the rounds of ring process left to do, default is 0,
> @@ -71,6 +71,10 @@ let notify dom = match dom.port with
> 	Event.notify dom.eventchn port
> 
> let bind_interdomain dom =
> +	begin match dom.port with
> +	| None -> ()
> +	| Some port -> Event.unbind dom.eventchn port
> +	end;
> 	dom.port <- Some (Event.bind_interdomain dom.eventchn dom.id dom.remote_port);
> 	debug "bound domain %d remote port %d to local port %s" dom.id dom.remote_port (string_of_port dom.port)
> 
> diff --git a/tools/ocaml/xenstored/process.ml b/tools/ocaml/xenstored/process.ml
> index 8a7e538..ff5c948 100644
> --- a/tools/ocaml/xenstored/process.ml
> +++ b/tools/ocaml/xenstored/process.ml
> @@ -408,7 +408,13 @@ let do_introduce con _t domains cons data =
> 		in
> 	let dom =
> 		if Domains.exist domains domid then
> -			Domains.find domains domid
> +			let edom = Domains.find domains domid in
> +			if (Domain.get_mfn edom) = mfn && (Connections.find_domain cons domid) != con then begin
> +				(* Use XS_INTRODUCE for recreating the xenbus event-channel. *)
> +				edom.remote_port <- port;
> +				Domain.bind_interdomain edom;
> +			end;
> +			edom
> 		else try
> 			let ndom = Domains.create domains domid mfn port in
> 			Connections.add_domain cons ndom;
> -- 
> 2.7.4
>
Igor Druzhinin Aug. 20, 2019, 10:45 a.m. UTC | #2
On 20/08/2019 09:21, Christian Lindig wrote:
>> +			if (Domain.get_mfn edom) = mfn && (Connections.find_domain cons domid) != con then begin
> 
> This should use <> instead of != because != is pointer inequality in OCaml. The parentheses are not strictly necessary because function application has precedence. So:
> 
> 	if Domain.get_mfn edom = mfn && Connections.find_domain cons domid <> con then begin
> 

But I actually want to compare pointers here - the idea is that the
connection object in the hashtable indexed by domid is not the same as
connection that we got XS_INTRODUCE message from. (see
tools/xenstore/xenstrored_domain.c)

Igor

>> On 19 Aug 2019, at 19:45, Igor Druzhinin <igor.druzhinin@citrix.com> wrote:
>>
>> C version of xenstored had this ability since 61aaed0d5 ("Allow
>> XS_INTRODUCE to be used for rebinding the xenstore evtchn.") from 2007.
>> Copy it as is to Ocaml version.
>>
>> Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com>
>> ---
>> tools/ocaml/xenstored/domain.ml  | 6 +++++-
>> tools/ocaml/xenstored/process.ml | 8 +++++++-
>> 2 files changed, 12 insertions(+), 2 deletions(-)
>>
>> diff --git a/tools/ocaml/xenstored/domain.ml b/tools/ocaml/xenstored/domain.ml
>> index b0a01b0..aeb185f 100644
>> --- a/tools/ocaml/xenstored/domain.ml
>> +++ b/tools/ocaml/xenstored/domain.ml
>> @@ -23,9 +23,9 @@ type t =
>> {
>> 	id: Xenctrl.domid;
>> 	mfn: nativeint;
>> -	remote_port: int;
>> 	interface: Xenmmap.mmap_interface;
>> 	eventchn: Event.t;
>> +	mutable remote_port: int;
>> 	mutable port: Xeneventchn.t option;
>> 	mutable bad_client: bool;
>> 	mutable io_credit: int; (* the rounds of ring process left to do, default is 0,
>> @@ -71,6 +71,10 @@ let notify dom = match dom.port with
>> 	Event.notify dom.eventchn port
>>
>> let bind_interdomain dom =
>> +	begin match dom.port with
>> +	| None -> ()
>> +	| Some port -> Event.unbind dom.eventchn port
>> +	end;
>> 	dom.port <- Some (Event.bind_interdomain dom.eventchn dom.id dom.remote_port);
>> 	debug "bound domain %d remote port %d to local port %s" dom.id dom.remote_port (string_of_port dom.port)
>>
>> diff --git a/tools/ocaml/xenstored/process.ml b/tools/ocaml/xenstored/process.ml
>> index 8a7e538..ff5c948 100644
>> --- a/tools/ocaml/xenstored/process.ml
>> +++ b/tools/ocaml/xenstored/process.ml
>> @@ -408,7 +408,13 @@ let do_introduce con _t domains cons data =
>> 		in
>> 	let dom =
>> 		if Domains.exist domains domid then
>> -			Domains.find domains domid
>> +			let edom = Domains.find domains domid in
>> +			if (Domain.get_mfn edom) = mfn && (Connections.find_domain cons domid) != con then begin
>> +				(* Use XS_INTRODUCE for recreating the xenbus event-channel. *)
>> +				edom.remote_port <- port;
>> +				Domain.bind_interdomain edom;
>> +			end;
>> +			edom
>> 		else try
>> 			let ndom = Domains.create domains domid mfn port in
>> 			Connections.add_domain cons ndom;
>> -- 
>> 2.7.4
>>
>
Christian Lindig Aug. 20, 2019, 12:11 p.m. UTC | #3
> On 20 Aug 2019, at 11:45, Igor Druzhinin <igor.druzhinin@citrix.com> wrote:
> 
> On 20/08/2019 09:21, Christian Lindig wrote:
>>> +			if (Domain.get_mfn edom) = mfn && (Connections.find_domain cons domid) != con then begin
>> 
>> This should use <> instead of != because != is pointer inequality in OCaml. The parentheses are not strictly necessary because function application has precedence. So:
>> 
>> 	if Domain.get_mfn edom = mfn && Connections.find_domain cons domid <> con then begin
>> 
> 
> But I actually want to compare pointers here - the idea is that the
> connection object in the hashtable indexed by domid is not the same as
> connection that we got XS_INTRODUCE message from. (see
> tools/xenstore/xenstrored_domain.c)

In your code, a != b is true, if a and b have identical structure but different addresses. I strongly suspect that two connection values should have different structure to be considered different, not just different addresses. When a <> b is true, it implies a != b. So using a <> b is safe(r). By using != you would rely on an invariant that every connection (con) exists only once and is never copied.

— Christian
Igor Druzhinin Aug. 20, 2019, 12:45 p.m. UTC | #4
On 20/08/2019 13:11, Christian Lindig wrote:
> 
> 
>> On 20 Aug 2019, at 11:45, Igor Druzhinin <igor.druzhinin@citrix.com> wrote:
>>
>> On 20/08/2019 09:21, Christian Lindig wrote:
>>>> +			if (Domain.get_mfn edom) = mfn && (Connections.find_domain cons domid) != con then begin
>>>
>>> This should use <> instead of != because != is pointer inequality in OCaml. The parentheses are not strictly necessary because function application has precedence. So:
>>>
>>> 	if Domain.get_mfn edom = mfn && Connections.find_domain cons domid <> con then begin
>>>
>>
>> But I actually want to compare pointers here - the idea is that the
>> connection object in the hashtable indexed by domid is not the same as
>> connection that we got XS_INTRODUCE message from. (see
>> tools/xenstore/xenstrored_domain.c)
> 
> In your code, a != b is true, if a and b have identical structure but different addresses. I strongly suspect that two connection values should have different structure to be considered different, not just different addresses. When a <> b is true, it implies a != b. So using a <> b is safe(r). By using != you would rely on an invariant that every connection (con) exists only once and is never copied.
> 

Connection is a complex object (has various counters and internal
structures) and I don't think simple field by field comparison (is <>
just that in Ocaml?) is appropriate here.

con is passed into that function from xenstored.ml where it's extracted
from the same hashtable (Connections) so it's actually the exactly same
object. There are other examples in connections.ml where pointer
comparison is used to compare connections.

Igor
Christian Lindig Aug. 20, 2019, 1:09 p.m. UTC | #5
> On 20 Aug 2019, at 13:45, Igor Druzhinin <igor.druzhinin@citrix.com> wrote:
> 
> con is passed into that function from xenstored.ml where it's extracted
> from the same hashtable (Connections) so it's actually the exactly same
> object. 

This comes down to what semantics you want. It is unfortunate that Connection.t is not abstract and its equality not well defined. Using != now relies on the fact that you only compare values stored in the same hash table.

— C

Acked-by: Christian Lindig <christian.lindig@citrix.com>
diff mbox series

Patch

diff --git a/tools/ocaml/xenstored/domain.ml b/tools/ocaml/xenstored/domain.ml
index b0a01b0..aeb185f 100644
--- a/tools/ocaml/xenstored/domain.ml
+++ b/tools/ocaml/xenstored/domain.ml
@@ -23,9 +23,9 @@  type t =
 {
 	id: Xenctrl.domid;
 	mfn: nativeint;
-	remote_port: int;
 	interface: Xenmmap.mmap_interface;
 	eventchn: Event.t;
+	mutable remote_port: int;
 	mutable port: Xeneventchn.t option;
 	mutable bad_client: bool;
 	mutable io_credit: int; (* the rounds of ring process left to do, default is 0,
@@ -71,6 +71,10 @@  let notify dom = match dom.port with
 	Event.notify dom.eventchn port
 
 let bind_interdomain dom =
+	begin match dom.port with
+	| None -> ()
+	| Some port -> Event.unbind dom.eventchn port
+	end;
 	dom.port <- Some (Event.bind_interdomain dom.eventchn dom.id dom.remote_port);
 	debug "bound domain %d remote port %d to local port %s" dom.id dom.remote_port (string_of_port dom.port)
 
diff --git a/tools/ocaml/xenstored/process.ml b/tools/ocaml/xenstored/process.ml
index 8a7e538..ff5c948 100644
--- a/tools/ocaml/xenstored/process.ml
+++ b/tools/ocaml/xenstored/process.ml
@@ -408,7 +408,13 @@  let do_introduce con _t domains cons data =
 		in
 	let dom =
 		if Domains.exist domains domid then
-			Domains.find domains domid
+			let edom = Domains.find domains domid in
+			if (Domain.get_mfn edom) = mfn && (Connections.find_domain cons domid) != con then begin
+				(* Use XS_INTRODUCE for recreating the xenbus event-channel. *)
+				edom.remote_port <- port;
+				Domain.bind_interdomain edom;
+			end;
+			edom
 		else try
 			let ndom = Domains.create domains domid mfn port in
 			Connections.add_domain cons ndom;