diff --git a/tools/ocaml/xenstored/perms.ml b/tools/ocaml/xenstored/perms.ml index e8a16221f8..84f2503e8e 100644 --- a/tools/ocaml/xenstored/perms.ml +++ b/tools/ocaml/xenstored/perms.ml @@ -64,8 +64,7 @@ let get_owner perm = perm.owner * *) let remove_domid ~domid perm = let acl = List.filter (fun (acl_domid, _) -> acl_domid <> domid) perm.acl in - let owner = if perm.owner = domid then 0 else perm.owner in - { perm with acl; owner } + if perm.owner = domid then None else Some { perm with acl; owner = perm.owner } let default0 = create 0 NONE [] diff --git a/tools/ocaml/xenstored/store.ml b/tools/ocaml/xenstored/store.ml index 328d3a5198..d82764f60f 100644 --- a/tools/ocaml/xenstored/store.ml +++ b/tools/ocaml/xenstored/store.ml @@ -89,10 +89,21 @@ let check_owner node connection = let rec recurse fct node = fct node; List.iter (recurse fct) node.children -(** [recurse_map f tree] applies [f] on each node in the tree recursively *) -let recurse_map f = +(** [recurse_filter_map f tree] applies [f] on each node in the tree recursively, + possibly removing some nodes. + Note that the nodes removed this way won't generate watch events. +*) +let recurse_filter_map f = + let invalid = -1 in + let is_valid node = node.perms.owner <> invalid in let rec walk node = - f { node with children = List.rev_map walk node.children |> List.rev } + (* Map.filter_map is Ocaml 4.11+ only *) + let node = + { node with children = + List.rev_map walk node.children |> List.filter is_valid |> List.rev } in + match f node with + | Some keep -> keep + | None -> { node with perms = {node.perms with owner = invalid } } in walk @@ -446,11 +457,13 @@ let setperms store perm path nperms = let reset_permissions store domid = Logging.info "store|node" "Cleaning up xenstore ACLs for domid %d" domid; - store.root <- Node.recurse_map (fun node -> - let perms = Perms.Node.remove_domid ~domid node.perms in - if perms <> node.perms then - Logging.debug "store|node" "Changed permissions for node %s" (Node.get_name node); - { node with perms } + store.root <- Node.recurse_filter_map (fun node -> + match Perms.Node.remove_domid ~domid node.perms with + | None -> None + | Some perms -> + if perms <> node.perms then + Logging.debug "store|node" "Changed permissions for node %s" (Node.get_name node); + Some { node with perms } ) store.root type ops = {