Motr  M0
flip_fom.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-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 
22 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_SPIEL
23 #include "lib/trace.h"
24 #include "lib/errno.h"
25 #include "lib/memory.h"
26 #include "lib/string.h" /* strlen, m0_strdup */
27 #include "lib/tlist.h"
28 #include "lib/assert.h"
29 #include "lib/finject.h" /* M0_FI_ENABLED */
30 #include "lib/fs.h" /* m0_file_read */
31 #include "conf/confd.h"
32 #include "conf/confd_stob.h"
33 #include "conf/flip_fop.h"
34 #include "conf/flip_fom.h"
35 #include "conf/obj_ops.h" /* m0_conf_obj_find */
36 #include "fop/fop.h"
37 #include "motr/magic.h"
38 #ifndef __KERNEL__
39  #include "motr/setup.h"
40  #include <sys/stat.h>
41  #include <unistd.h>
42  #include <fcntl.h>
43 #endif
44 
50 M0_TL_DECLARE(m0_conf_cache, M0_INTERNAL, struct m0_conf_obj);
51 
52 static int conf_flip_fom_tick(struct m0_fom *fom);
53 static void conf_flip_fom_fini(struct m0_fom *fom);
54 
55 static int conf_flip_prepare(struct m0_fom *);
56 static int conf_flip_apply(struct m0_fom *);
57 
58 static size_t conf_flip_fom_home_locality(const struct m0_fom *fom);
59 
63 const struct m0_fom_ops conf_flip_fom_ops = {
65  .fo_tick = conf_flip_fom_tick,
66  .fo_home_locality = conf_flip_fom_home_locality,
67 };
68 
74 };
75 
82  .sd_name = "Conf_flip_Prepare",
83  .sd_allowed = M0_BITS(M0_FOPH_CONF_APPLY,
85  },
86  [M0_FOPH_CONF_APPLY] = {
87  .sd_name = "Conf_Flip_Apply",
88  .sd_allowed = M0_BITS(M0_FOPH_SUCCESS,
90  },
91 };
92 
93 
95  .scf_name = "Conf_Flip_phases",
96  .scf_nr_states = ARRAY_SIZE(conf_flip_phases),
97  .scf_state = conf_flip_phases,
98 };
99 
103 static bool conf_flip_fom_invariant(const struct m0_conf_flip_fom *fom)
104 {
105  return _0C(fom != NULL);
106 }
107 
121 M0_INTERNAL int m0_conf_flip_fom_create(struct m0_fop *fop,
122  struct m0_fom **out,
123  struct m0_reqh *reqh)
124 {
125  struct m0_fom *fom;
126  struct m0_conf_flip_fom *conf_flip_fom;
127  struct m0_fop *rep_fop;
128 
129  M0_PRE(fop != NULL);
131  M0_PRE(out != NULL);
132  M0_PRE(reqh != NULL);
133 
134  M0_ENTRY("fop=%p", fop);
135 
136  M0_ALLOC_PTR(conf_flip_fom);
138  if (conf_flip_fom == NULL || rep_fop == NULL) {
139  m0_free(conf_flip_fom);
140  m0_free(rep_fop);
141  return M0_RC(-ENOMEM);
142  }
143 
144  fom = &conf_flip_fom->clm_gen;
145  *out = fom;
147  fop, rep_fop, reqh);
148 
149  M0_LOG(M0_DEBUG, "fom=%p", fom);
150  return M0_RC(0);
151 }
152 
153 static int conf_flip_prepare(struct m0_fom *fom)
154 {
155  M0_ENTRY("fom=%p", fom);
157  return M0_RC(M0_FSO_AGAIN);
158 }
159 
160 /* Save confd configuration STOB */
162  char *buffer)
163 {
164  int rc = 0;
165 #ifndef __KERNEL__
166  int fd;
167  size_t length;
168 
169  M0_ENTRY();
170 
171  if(M0_FI_ENABLED("fcreate_failed"))
172  return M0_ERR(-EACCES);
173  fd = open(filename, O_TRUNC | O_CREAT | O_WRONLY, 0700);
174 
175  if (fd == -1)
176  return M0_ERR(-errno);
177 
178  length = strlen(buffer);
179  rc = write(fd, buffer, length) == length ? 0 : M0_ERR(-EINVAL);
180  fsync(fd);
181  close(fd);
182 #endif /* __KERNEL__ */
183  return M0_RC(rc);
184 }
185 
192 static int conf_after_flip_apply(struct m0_reqh *reqh, const char *filename)
193 {
194  struct m0_rconfc *rconfc = &reqh->rh_rconfc;
195  struct m0_fid profile = rconfc->rc_profile;
196  struct m0_sm_group *sm_grp = rconfc->rc_sm.sm_grp;
197  struct m0_rpc_machine *rmach = rconfc->rc_rmach;
199  m0_rconfc_cb_t ready_cb = rconfc->rc_ready_cb;
200  char *local_conf;
201  int rc;
202 
203  M0_ENTRY();
206  if (rc != 0)
207  return M0_ERR(rc);
208  /*
209  * Although m0_rconfc_stop_sync() launches an ast internally, there is
210  * nothing to wait for in the pre-loaded rconfc. So hopefully this is to
211  * do no harm to fom tick, but heavily simplify the reload.
212  */
215  rc = m0_rconfc_init(rconfc, &profile, sm_grp, rmach, exp_cb, ready_cb);
216  if (rc != 0) {
218  return M0_ERR(rc);
219  }
221  /*
222  * Despite the name, m0_rconfc_start_sync() does no waiting at all with
223  * local conf pre-loading.
224  */
226 }
227 
242 static int conf_flip_apply(struct m0_fom *fom)
243 {
244  int rc;
245  struct m0_conf_flip_fom *conf_fom;
246  struct m0_fop_conf_flip *conf_fop;
247  struct m0_stob *stob = NULL;
248  char *location;
249  char *conf_filename = NULL;
250  struct m0_confd *confd;
251  char *confd_buffer = NULL;
252  struct m0_conf_cache *new_cache;
253 
254  M0_ENTRY("fom=%p", fom);
255 
256  M0_PRE(fom != NULL);
257  M0_PRE(m0_is_conf_flip_fop(fom->fo_fop));
259 
260  conf_fom = container_of(fom, struct m0_conf_flip_fom, clm_gen);
262 
263  conf_fop = m0_conf_fop_to_flip_fop(fom->fo_fop);
264 
265  /* Reads data of previous "Load command" aka stob */
268  &M0_CONFD_FID(conf_fop->cff_prev_version,
269  conf_fop->cff_next_version,
270  conf_fop->cff_tx_id)) ?:
271  m0_confd_stob_read(stob, &confd_buffer);
272  if (rc != 0)
273  goto done;
274 
275  confd = bob_of(fom->fo_service, struct m0_confd, d_reqh, &m0_confd_bob);
276 
277  /*
278  * Create new cache and use it in confd instead of a current cache.
279  * Save new cache in a file used by confd on startup, so confd will use
280  * new configuration db after restart.
281  * If something fails, then don't touch current cache at all.
282  */
283  rc = m0_confd_service_to_filename(fom->fo_service, &conf_filename) ?:
284  m0_confd_cache_create(&new_cache, &confd->d_cache_lock,
285  confd_buffer) ?:
286  conf_flip_confd_config_save(conf_filename, confd_buffer) ?:
287  conf_after_flip_apply(m0_fom2reqh(fom), conf_filename);
288  if (rc == 0) {
290  confd->d_cache = new_cache;
291  } else if (new_cache != NULL)
292  m0_confd_cache_destroy(new_cache);
293 done:
294  if (confd_buffer != NULL)
295  m0_free_aligned(confd_buffer, strlen(confd_buffer) + 1,
298  m0_free(location);
299  m0_free(conf_filename);
301  return M0_RC(M0_FSO_AGAIN);
302 }
303 
312 static int conf_flip_fom_tick(struct m0_fom *fom)
313 {
314  int rc = 0;
315  struct m0_conf_flip_fom *conf_fom;
316  struct m0_fop_conf_flip_rep *rep;
317 
318  M0_ENTRY("fom %p", fom);
319 
320  M0_PRE(fom != NULL);
321  M0_PRE(m0_is_conf_flip_fop(fom->fo_fop));
322 
323  if (m0_fom_phase(fom) < M0_FOPH_NR)
324  return m0_fom_tick_generic(fom);
325 
326  conf_fom = container_of(fom, struct m0_conf_flip_fom, clm_gen);
328 
329  switch (m0_fom_phase(fom)) {
332  break;
333  case M0_FOPH_CONF_APPLY:
335  break;
336  default:
337  M0_ASSERT(0);
338  break;
339  }
340 
342  rep = m0_conf_fop_to_flip_fop_rep(fom->fo_rep_fop);
343  rep->cffr_rc = m0_fom_rc(fom);
344  }
345 
346  return M0_RC(rc);
347 }
348 
357 static void conf_flip_fom_fini(struct m0_fom *fom)
358 {
359  struct m0_conf_flip_fom *conf_fom;
360 
361  M0_PRE(fom != NULL);
362 
363  conf_fom = container_of(fom, struct m0_conf_flip_fom, clm_gen);
365 
366  m0_fom_fini(fom);
367  m0_free(conf_fom);
368 }
369 
370 static size_t conf_flip_fom_home_locality(const struct m0_fom *fom)
371 {
372  M0_ENTRY();
373  M0_PRE(fom != NULL);
374  M0_LEAVE();
375  return 1;
376 }
377 
378 #undef M0_TRACE_SUBSYSTEM
379 
382 /*
383  * Local variables:
384  * c-indentation-style: "K&R"
385  * c-basic-offset: 8
386  * tab-width: 8
387  * fill-column: 80
388  * scroll-step: 1
389  * End:
390  */
struct m0_sm rc_sm
Definition: rconfc.h:247
#define M0_CONFD_FID(old_version, new_version, tx_id)
Definition: confd_stob.h:39
static size_t conf_flip_fom_home_locality(const struct m0_fom *fom)
Definition: flip_fom.c:370
void m0_fom_phase_moveif(struct m0_fom *fom, int32_t rc, int phase0, int phase1)
Definition: fom.c:1710
static int conf_flip_prepare(struct m0_fom *)
Definition: flip_fom.c:153
#define M0_PRE(cond)
char * rc_local_conf
Definition: rconfc.h:390
#define NULL
Definition: misc.h:38
Definition: sm.h:350
struct m0_fop_type m0_fop_conf_flip_rep_fopt
Definition: fop.c:68
#define M0_LOG(level,...)
Definition: trace.h:167
M0_LEAVE()
M0_INTERNAL int m0_file_read(const char *path, char **out)
Definition: fs.c:61
void(* m0_rconfc_cb_t)(struct m0_rconfc *rconfc)
Definition: rconfc.h:215
int(* fto_create)(struct m0_fop *fop, struct m0_fom **out, struct m0_reqh *reqh)
Definition: fom.h:650
M0_INTERNAL void m0_rconfc_stop_sync(struct m0_rconfc *rconfc)
Definition: rconfc.c:2995
M0_INTERNAL void m0_free_aligned(void *data, size_t size, unsigned shift)
Definition: memory.c:192
#define M0_BITS(...)
Definition: misc.h:236
struct m0_rpc_machine * rc_rmach
Definition: rconfc.h:318
#define container_of(ptr, type, member)
Definition: misc.h:33
struct m0_fop_getxattr_rep * rep
Definition: dir.c:455
static int conf_after_flip_apply(struct m0_reqh *reqh, const char *filename)
Definition: flip_fom.c:192
m0_fom_phase
Definition: fom.h:372
const char * location
Definition: storage.c:50
struct m0_fom_type ft_fom_type
Definition: fop.h:232
struct m0_mutex d_cache_lock
Definition: confd.h:156
return M0_RC(rc)
M0_INTERNAL uint32_t m0_stob_block_shift(struct m0_stob *stob)
Definition: stob.c:270
#define M0_ENTRY(...)
Definition: trace.h:170
M0_TL_DECLARE(m0_conf_cache, M0_INTERNAL, struct m0_conf_obj)
M0_INTERNAL int m0_confd_service_to_filename(struct m0_reqh_service *service, char **dbpath)
Definition: confd.c:624
void m0_fom_init(struct m0_fom *fom, const struct m0_fom_type *fom_type, const struct m0_fom_ops *ops, struct m0_fop *fop, struct m0_fop *reply, struct m0_reqh *reqh)
Definition: fom.c:1372
struct m0_fop_type * f_type
Definition: fop.h:81
static int conf_flip_fom_tick(struct m0_fom *fom)
Definition: flip_fom.c:312
static int conf_flip_apply(struct m0_fom *)
Definition: flip_fom.c:242
static int conf_flip_confd_config_save(char *filename, char *buffer)
Definition: flip_fom.c:161
return M0_ERR(-EOPNOTSUPP)
void m0_confd_stob_fini(struct m0_stob *stob)
Definition: confd_stob.c:104
M0_INTERNAL int m0_conf_stob_location_generate(struct m0_fom *fom, char **location)
Definition: confd_stob.c:181
Definition: stob.h:163
int m0_fom_tick_generic(struct m0_fom *fom)
Definition: fom_generic.c:848
void m0_fom_fini(struct m0_fom *fom)
Definition: fom.c:1324
static struct m0_stob * stob
Definition: storage.c:39
#define M0_ASSERT(cond)
const char * scf_name
Definition: sm.h:352
const struct m0_fom_ops conf_flip_fom_ops
Definition: flip_fom.c:63
const struct m0_bob_type m0_confd_bob
Definition: confd.c:443
#define bob_of(ptr, type, field, bt)
Definition: bob.h:140
M0_INTERNAL int m0_confd_cache_create(struct m0_conf_cache **out, struct m0_mutex *cache_lock, const char *confstr)
Definition: confd.c:513
int m0_confd_stob_init(struct m0_stob **stob, const char *location, struct m0_fid *confd_fid)
Definition: confd_stob.c:50
static char local_conf[]
Definition: file.c:115
M0_INTERNAL bool m0_rconfc_is_preloaded(struct m0_rconfc *rconfc)
Definition: rconfc.c:3135
struct m0_sm_group * sm_grp
Definition: sm.h:321
struct m0_fid rc_profile
Definition: rconfc.h:392
static int m0_rconfc_start_sync(struct m0_rconfc *rconfc)
Definition: rconfc.h:502
Definition: reqh.h:94
Definition: dump.c:103
M0_INTERNAL void m0_confd_cache_destroy(struct m0_conf_cache *cache)
Definition: confd.c:536
uint32_t cff_prev_version
Definition: flip_fop.h:83
struct m0_sm_conf conf_flip_conf
Definition: flip_fom.c:94
M0_INTERNAL void m0_rconfc_fini(struct m0_rconfc *rconfc)
Definition: rconfc.c:3009
struct m0_fop * m0_fop_reply_alloc(struct m0_fop *req, struct m0_fop_type *rept)
Definition: fop.c:129
struct m0_conf_cache * d_cache
Definition: confd.h:163
uint32_t sd_flags
Definition: sm.h:378
Definition: fom.h:481
uint32_t cff_next_version
Definition: flip_fop.h:85
m0_rconfc_cb_t rc_expired_cb
Definition: rconfc.h:278
struct m0_reqh reqh
Definition: rm_foms.c:48
static struct m0_fid profile
Definition: rconfc.c:49
#define M0_FI_ENABLED(tag)
Definition: finject.h:231
Definition: fid.h:38
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
const struct m0_fom_type_ops conf_flip_fom_type_ops
Definition: flip_fom.c:72
struct m0_fom clm_gen
Definition: flip_fom.h:62
Definition: addb2.c:200
M0_INTERNAL int m0_fom_rc(const struct m0_fom *fom)
Definition: fom.c:1727
#define _0C(exp)
Definition: assert.h:311
uint64_t cff_tx_id
Definition: flip_fop.h:87
static struct m0_fop * fop
Definition: item.c:57
struct m0t1fs_filedata * fd
Definition: dir.c:1030
static struct m0_rconfc * rconfc(struct m0_client *m0c)
Definition: client_init.c:310
void(* fo_fini)(struct m0_fom *fom)
Definition: fom.h:657
struct m0_rconfc rh_rconfc
Definition: reqh.h:166
static unsigned done
Definition: storage.c:91
int m0_confd_stob_read(struct m0_stob *stob, char **str)
Definition: confd_stob.c:135
M0_INTERNAL int m0_rconfc_init(struct m0_rconfc *rconfc, const struct m0_fid *profile, struct m0_sm_group *sm_group, struct m0_rpc_machine *rmach, m0_rconfc_cb_t expired_cb, m0_rconfc_cb_t ready_cb)
Definition: rconfc.c:2860
#define out(...)
Definition: gen.c:41
M0_INTERNAL struct m0_fop_conf_flip * m0_conf_fop_to_flip_fop(const struct m0_fop *fop)
Definition: flip_fop.c:42
void m0_fom_phase_set(struct m0_fom *fom, int phase)
Definition: fom.c:1688
static bool conf_flip_fom_invariant(const struct m0_conf_flip_fom *fom)
Definition: flip_fom.c:103
M0_INTERNAL bool m0_is_conf_flip_fop(const struct m0_fop *fop)
Definition: flip_fop.c:30
void m0_free(void *data)
Definition: memory.c:146
M0_INTERNAL int m0_conf_flip_fom_create(struct m0_fop *fop, struct m0_fom **out, struct m0_reqh *reqh)
Definition: flip_fom.c:121
struct m0_sm_state_descr conf_flip_phases[]
Definition: flip_fom.c:79
M0_INTERNAL struct m0_reqh * m0_fom2reqh(const struct m0_fom *fom)
Definition: fom.c:1749
int32_t rc
Definition: trigger_fop.h:47
#define ARRAY_SIZE(a)
Definition: misc.h:45
M0_INTERNAL struct m0_fop_conf_flip_rep * m0_conf_fop_to_flip_fop_rep(const struct m0_fop *fop)
Definition: flip_fop.c:51
static void conf_flip_fom_fini(struct m0_fom *fom)
Definition: flip_fom.c:357
m0_rconfc_cb_t rc_ready_cb
Definition: rconfc.h:294
Definition: fop.h:79
struct m0_fop * rep_fop
Definition: dir.c:334