Motr  M0
walk.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016-2020 Seagate Technology LLC and/or its Affiliates
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * For any questions about this software or licensing,
17  * please email opensource@seagate.com or cortx-questions@seagate.com.
18  *
19  */
20 
21 
28 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_CONF
29 #include "lib/trace.h"
30 
31 #include "conf/walk.h"
32 #include "conf/cache.h" /* m0_conf_cache_is_locked */
33 #include "conf/obj_ops.h" /* m0_conf_obj_invariant */
34 #include "conf/dir.h" /* m0_conf_dir_tl */
35 
36 struct conf_walker {
38  int (*cw_fn)(struct m0_conf_obj *obj, void *args);
40  bool cw_down_p;
41 };
42 
43 static int conf_walker_down(struct conf_walker *w, void *args);
44 static int conf_walker_up(struct conf_walker *w);
45 static struct m0_conf_obj *conf_downlink_first(const struct m0_conf_obj *obj);
46 static struct m0_conf_obj *conf_downlink_next(const struct m0_conf_obj *parent,
47  const struct m0_conf_obj *child);
48 
49 M0_INTERNAL int m0_conf_walk(int (*fn)(struct m0_conf_obj *obj, void *args),
50  struct m0_conf_obj *origin, void *args)
51 {
52  struct conf_walker w = {
53  .cw_origin = origin,
54  .cw_fn = fn,
55  .cw_cur = origin,
56  .cw_down_p = true
57  };
58  int rc;
59 
62  while (1) {
63  rc = w.cw_down_p ? conf_walker_down(&w, args) :
64  conf_walker_up(&w);
65  if (rc < 0 || rc == M0_CW_STOP)
66  return rc;
68  }
69 }
70 
71 static void conf_walker_turn(struct conf_walker *w)
72 {
73  w->cw_down_p = !w->cw_down_p;
74 }
75 
76 static int conf_walker_down(struct conf_walker *w, void *args)
77 {
78  struct m0_conf_obj *obj = w->cw_cur;
79  int rc;
80 
81  M0_PRE(w->cw_down_p);
83 
84  rc = w->cw_fn(obj, args);
85  if (rc < 0 || rc == M0_CW_STOP)
86  return M0_RC(rc);
87  if (rc == M0_CW_SKIP_SIBLINGS) {
88  if (obj->co_parent == NULL)
90  else
91  w->cw_cur = obj->co_parent;
93  return M0_RC(M0_CW_CONTINUE);
94  }
97  return M0_RC(M0_CW_CONTINUE);
98  }
101  if (obj == NULL)
102  conf_walker_turn(w);
103  else
104  w->cw_cur = obj;
105  return M0_RC(M0_CW_CONTINUE);
106 }
107 
108 static int conf_walker_up(struct conf_walker *w)
109 {
110  struct m0_conf_obj *parent;
111 
112  M0_PRE(!w->cw_down_p);
114 
115  if (w->cw_cur == w->cw_origin)
116  return M0_RC(M0_CW_STOP); /* end of traversal */
117 
118  parent = w->cw_cur->co_parent;
119  w->cw_cur = conf_downlink_next(parent, w->cw_cur);
120  if (w->cw_cur == NULL)
121  w->cw_cur = parent; /* no more downlinks; go up */
122  else
123  conf_walker_turn(w); /* found unvisited downlink; go down */
124  return M0_RC(M0_CW_CONTINUE);
125 }
126 
127 static struct m0_conf_obj *conf_downlink_first(const struct m0_conf_obj *obj)
128 {
129  const struct m0_fid **rels;
130  struct m0_conf_obj *x;
131  int rc;
132 
134  return m0_conf_dir_tlist_head(
135  &M0_CONF_CAST(obj, m0_conf_dir)->cd_items);
136  rels = obj->co_ops->coo_downlinks(obj);
137  if (*rels == NULL)
138  return NULL;
139  rc = obj->co_ops->coo_lookup(obj, *rels, &x);
140  M0_ASSERT(rc == 0); /* downlinks are guaranteed to be valid */
141  return x;
142 }
143 
144 static struct m0_conf_obj *conf_downlink_next(const struct m0_conf_obj *parent,
145  const struct m0_conf_obj *child)
146 {
147  const struct m0_fid **rels;
148  struct m0_conf_obj *x;
149  bool child_found_p = false;
150  int rc;
151 
152  if (m0_conf_obj_type(parent) == &M0_CONF_DIR_TYPE)
153  return m0_conf_dir_tlist_next(
154  &M0_CONF_CAST(parent, m0_conf_dir)->cd_items, child);
155  for (rels = parent->co_ops->coo_downlinks(parent); *rels != NULL;
156  ++rels) {
157  rc = parent->co_ops->coo_lookup(parent, *rels, &x);
158  M0_ASSERT(rc == 0); /* downlinks are guaranteed to be valid */
159  if (child_found_p)
160  return x;
161  if (x == child)
162  child_found_p = true;
163  }
164  M0_ASSERT_INFO(child_found_p, "No downlink from "FID_F" to "FID_F,
165  FID_P(&parent->co_id), FID_P(&child->co_id));
166  return NULL;
167 }
168 
169 #undef M0_TRACE_SUBSYSTEM
170 
const struct m0_conf_obj_type * m0_conf_obj_type(const struct m0_conf_obj *obj)
Definition: obj.c:363
struct m0_fid co_id
Definition: obj.h:208
#define M0_PRE(cond)
#define NULL
Definition: misc.h:38
static bool x
Definition: sm.c:168
struct m0_conf_obj * cw_origin
Definition: walk.c:37
static struct m0_conf_obj * conf_downlink_next(const struct m0_conf_obj *parent, const struct m0_conf_obj *child)
Definition: walk.c:144
const struct m0_conf_obj_type M0_CONF_ROOT_TYPE
Definition: root.c:214
struct m0_conf_cache * co_cache
Definition: obj.h:251
Definition: ub.c:49
struct m0_conf_obj * co_parent
Definition: obj.h:223
M0_INTERNAL bool m0_conf_obj_is_stub(const struct m0_conf_obj *obj)
Definition: obj.c:302
static struct foo * obj
Definition: tlist.c:302
return M0_RC(rc)
def args
Definition: addb2db.py:716
static void conf_walker_turn(struct conf_walker *w)
Definition: walk.c:71
M0_INTERNAL int m0_conf_walk(int(*fn)(struct m0_conf_obj *obj, void *args), struct m0_conf_obj *origin, void *args)
Definition: walk.c:49
#define M0_ASSERT(cond)
const struct m0_fid **(* coo_downlinks)(const struct m0_conf_obj *obj)
Definition: obj_ops.h:151
struct m0_conf_obj * cw_cur
Definition: walk.c:39
bool cw_down_p
Definition: walk.c:40
M0_INTERNAL bool m0_conf_cache_is_locked(const struct m0_conf_cache *cache)
Definition: cache.c:60
#define M0_CONF_CAST(ptr, type)
Definition: obj.h:780
#define FID_P(f)
Definition: fid.h:77
static int conf_walker_down(struct conf_walker *w, void *args)
Definition: walk.c:76
static struct m0_conf_obj * conf_downlink_first(const struct m0_conf_obj *obj)
Definition: walk.c:127
Definition: fid.h:38
int(* coo_lookup)(const struct m0_conf_obj *parent, const struct m0_fid *name, struct m0_conf_obj **out)
Definition: obj_ops.h:118
int(* cw_fn)(struct m0_conf_obj *obj, void *args)
Definition: walk.c:38
#define M0_ASSERT_INFO(cond, fmt,...)
const struct m0_conf_obj_type M0_CONF_DIR_TYPE
Definition: dir.c:206
static int conf_walker_up(struct conf_walker *w)
Definition: walk.c:108
int32_t rc
Definition: trigger_fop.h:47
M0_INTERNAL bool m0_conf_obj_invariant(const struct m0_conf_obj *obj)
Definition: obj_ops.c:52
#define FID_F
Definition: fid.h:75
const struct m0_conf_obj_ops * co_ops
Definition: obj.h:212