Motr  M0
io.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2014-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_STOB
24 #include "lib/errno.h" /* ENOMEM */
25 #include "lib/memory.h"
26 #include "lib/trace.h"
27 #include "addb2/addb2.h"
28 #include "fol/fol.h" /* m0_fol_frag */
29 
30 #include "stob/io.h"
31 #include "stob/stob.h" /* m0_stob_state_get */
32 #include "stob/domain.h" /* m0_stob_domain_id_get */
33 #include "stob/addb2.h"
34 
42 {
43  if (io->si_stob_private != NULL) {
44  io->si_op->sio_fini(io);
46  }
47 }
48 
49 M0_INTERNAL int m0_stob_io_private_setup(struct m0_stob_io *io,
50  struct m0_stob *obj)
51 {
52  uint8_t type_id;
53  int result;
54 
55  type_id = m0_stob_domain__type_id(
57  if (io->si_stob_magic != type_id) {
59  result = obj->so_ops->sop_io_init(obj, io);
60  io->si_stob_magic = type_id;
61  } else
62  result = 0;
63  return result;
64 }
65 
66 static void stob_io_addb2_add_and_push(uint64_t id,
67  struct m0_stob_io *io,
68  struct m0_stob *obj)
69 {
70  const struct m0_fid *fid = m0_stob_fid_get(obj);
71  struct m0_indexvec *iv = &io->si_stob;
72  struct m0_bufvec *bv = &io->si_user;
73  m0_bcount_t bvec_count;
74 
75  bvec_count = m0_vec_count(&bv->ov_vec);
76  M0_ADDB2_ADD(id, FID_P(fid),
77  bvec_count,
78  bv->ov_vec.v_nr, iv->iv_vec.v_nr, iv->iv_index[0]);
79  M0_ADDB2_PUSH(id, FID_P(fid),
80  bvec_count,
81  bv->ov_vec.v_nr, iv->iv_vec.v_nr, iv->iv_index[0]);
82 
88  bvec_count);
91  bvec_count << m0_stob_block_shift(obj));
92 }
93 
94 static bool stob_io_invariant(struct m0_stob_io *io, struct m0_stob *obj,
95  enum m0_stob_io_state state)
96 {
97  struct m0_indexvec *iv = &io->si_stob;
98  struct m0_bufvec *bv = &io->si_user;
99 
100  return _0C(m0_stob_state_get(obj) == CSS_EXISTS) &&
102  _0C(io->si_obj == NULL || ergo(state == SIS_PREPARED,
103  io->si_obj == obj)) &&
104  _0C(io->si_state == state) &&
105  _0C(io->si_opcode != SIO_INVALID) &&
106  _0C(m0_vec_count(&bv->ov_vec) == m0_vec_count(&iv->iv_vec)) &&
109 }
110 
111 M0_INTERNAL void m0_stob_io_init(struct m0_stob_io *io)
112 {
113  M0_SET0(io);
116  io->si_state = SIS_IDLE;
120 }
121 
122 M0_INTERNAL void m0_stob_io_fini(struct m0_stob_io *io)
123 {
124  M0_PRE(io->si_state == SIS_IDLE);
128 }
129 
130 M0_INTERNAL void m0_stob_io_credit(const struct m0_stob_io *io,
131  const struct m0_stob_domain *dom,
132  struct m0_be_tx_credit *accum)
133 {
136 }
137 
138 static void stob_io_fill(struct m0_stob_io *io,
139  struct m0_stob *obj,
140  struct m0_dtx *tx,
141  struct m0_io_scope *scope,
142  enum m0_stob_io_state state,
143  bool count_update)
144 {
145  io->si_obj = obj;
146  io->si_tx = tx;
147  io->si_scope = scope;
148  io->si_state = state;
149  io->si_rc = 0;
150  if (count_update)
151  io->si_count = 0;
152  io->si_start = m0_time_now();
153 }
154 
155 M0_INTERNAL int m0_stob_io_prepare(struct m0_stob_io *io, struct m0_stob *obj,
156  struct m0_dtx *tx, struct m0_io_scope *scope)
157 {
158  const struct m0_fid *fid = m0_stob_fid_get(obj);
159  uint8_t type_id;
160  int result;
161 
163  M0_ENTRY("stob=%p so_id="STOB_ID_F" si_opcode=%d io=%p tx=%p",
165  //stob_io_addb2_add_and_push(M0_AVI_STOB_IO_PREPARE, io, obj);
166  type_id = m0_stob_domain__type_id(
168  if (io->si_stob_magic != type_id) {
170  result = obj->so_ops->sop_io_init(obj, io);
171  io->si_stob_magic = type_id;
172  } else
173  result = 0;
174 
175  if (result == 0) {
176  stob_io_fill(io, obj, tx, scope, SIS_PREPARED, true);
177 
178  result = io->si_op->sio_prepare == NULL ? 0 :
179  io->si_op->sio_prepare(io);
180 
181  if (result != 0) {
182  M0_LOG(M0_ERROR, "io=%p "FID_F" FAILED rc=%d",
183  io, FID_P(fid), result);
184  io->si_state = SIS_IDLE;
185  }
186  }
187  //m0_addb2_pop(M0_AVI_STOB_IO_PREPARE);
188  M0_POST(ergo(result != 0, io->si_state == SIS_IDLE));
189  return result;
190 }
191 
192 M0_INTERNAL int m0_stob_io_launch(struct m0_stob_io *io, struct m0_stob *obj,
193  struct m0_dtx *tx, struct m0_io_scope *scope)
194 {
195  const struct m0_fid *fid = m0_stob_fid_get(obj);
196  int result;
197 
199  M0_ENTRY("stob=%p so_id="STOB_ID_F" si_opcode=%d io=%p tx=%p",
202  result = m0_stob_io_private_setup(io, obj);
203 
204  if (result == 0) {
205  stob_io_fill(io, obj, tx, scope, SIS_BUSY, false);
206 
207  result = io->si_op->sio_launch(io);
208  if (result != 0) {
209  M0_LOG(M0_ERROR, "io=%p "FID_F" FAILED rc=%d",
210  io, FID_P(fid), result);
211  io->si_state = SIS_IDLE;
212  }
213  }
215  M0_POST(ergo(result != 0, io->si_state == SIS_IDLE));
216  return result;
217 }
218 
220  struct m0_stob *obj,
221  struct m0_dtx *tx,
222  struct m0_io_scope *scope)
223 {
225 
226  return m0_stob_io_prepare(io, obj, tx, scope) ?:
227  m0_stob_io_launch(io, obj, tx, scope);
228 }
229 
230 M0_INTERNAL bool m0_stob_io_user_is_valid(const struct m0_bufvec *user)
231 {
232  return true;
233 }
234 
235 M0_INTERNAL bool m0_stob_io_stob_is_valid(const struct m0_indexvec *stob)
236 {
237  uint32_t i;
238  m0_bindex_t reached;
239 
240  for (reached = 0, i = 0; i < stob->iv_vec.v_nr; ++i) {
241  if (stob->iv_index[i] < reached)
242  return false;
243  reached = stob->iv_index[i] + stob->iv_vec.v_count[i];
244  }
245  return true;
246 }
247 
248 M0_INTERNAL int m0_stob_io_bufvec_launch(struct m0_stob *stob,
249  struct m0_bufvec *bufvec,
250  int op_code,
252 {
253  int rc;
254  struct m0_stob_io io;
255  struct m0_clink clink;
257  m0_bindex_t offset_idx = offset;
258 
259  M0_PRE(stob != NULL);
260  M0_PRE(bufvec != NULL);
261  M0_PRE(M0_IN(op_code, (SIO_READ, SIO_WRITE)));
262 
263  count = m0_vec_count(&bufvec->ov_vec);
265 
266  io.si_opcode = op_code;
267  io.si_flags = 0;
268  io.si_user.ov_vec.v_nr = bufvec->ov_vec.v_nr;
270  io.si_user.ov_buf = bufvec->ov_buf;
271  io.si_stob = (struct m0_indexvec) {
272  .iv_vec = { .v_nr = 1, .v_count = &count },
273  .iv_index = &offset_idx
274  };
275 
278 
280  if (rc == 0) {
282  rc = io.si_rc;
283  }
284 
287 
289 
290  return M0_RC(rc);
291 }
292 
293 M0_INTERNAL void *m0_stob_addr_pack(const void *buf, uint32_t shift)
294 {
295  uint64_t addr = (uint64_t)buf;
296 
297  M0_ASSERT_INFO(((addr >> shift) << shift) == addr,
298  "addr=%" PRIx64 " shift=%"PRIu32, addr, shift);
299  return (void *)(addr >> shift);
300 }
301 
302 M0_INTERNAL void *m0_stob_addr_open(const void *buf, uint32_t shift)
303 {
304  uint64_t addr = (uint64_t)buf;
305 
306  M0_ASSERT_INFO(((addr << shift) >> shift) == addr,
307  "addr=%" PRIx64 " shift=%"PRIu32, addr, shift);
308  return (void *)(addr << shift);
309 }
310 
311 M0_INTERNAL void m0_stob_iovec_sort(struct m0_stob_io *stob)
312 {
313  struct m0_indexvec *ivec = &stob->si_stob;
314  struct m0_bufvec *bvec = &stob->si_user;
315  int i;
316  bool exchanged;
317  bool separate_v_count;
318 
319 #define SWAP_NEXT(arr, idx) \
320 ({ \
321  int _idx = (idx); \
322  typeof(&arr[idx]) _arr = (arr); \
323  typeof(arr[idx]) _tmp; \
324  \
325  _tmp = _arr[_idx]; \
326  _arr[_idx] = _arr[_idx + 1]; \
327  _arr[_idx + 1] = _tmp; \
328 })
329 
330  separate_v_count = ivec->iv_vec.v_count != bvec->ov_vec.v_count;
331 
332  /*
333  * Bubble sort the index vectores.
334  * It also move bufvecs while sorting.
335  */
336  do {
337  exchanged = false;
338  for (i = 0; i < ivec->iv_vec.v_nr - 1; i++) {
339  if (ivec->iv_index[i] > ivec->iv_index[i + 1]) {
340 
341  SWAP_NEXT(ivec->iv_index, i);
342  SWAP_NEXT(ivec->iv_vec.v_count, i);
343  SWAP_NEXT(bvec->ov_buf, i);
344  if (separate_v_count)
346  exchanged = true;
347  }
348  }
349  } while (exchanged);
350 
351 #undef SWAP_NEXT
352 }
353 
354 #undef M0_TRACE_SUBSYSTEM
355 
358 /*
359  * Local variables:
360  * c-indentation-style: "K&R"
361  * c-basic-offset: 8
362  * tab-width: 8
363  * fill-column: 80
364  * scroll-step: 1
365  * End:
366  */
367 /*
368  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
369  */
M0_INTERNAL struct m0_stob_domain * m0_stob_dom_get(struct m0_stob *stob)
Definition: stob.c:338
M0_INTERNAL void m0_chan_wait(struct m0_clink *link)
Definition: chan.c:336
#define M0_PRE(cond)
Definition: dtm.h:554
enum m0_stob_io_flags si_flags
Definition: io.h:290
M0_INTERNAL int m0_stob_io_bufvec_launch(struct m0_stob *stob, struct m0_bufvec *bufvec, int op_code, m0_bindex_t offset)
Definition: io.c:248
M0_INTERNAL bool m0_stob_io_user_is_valid(const struct m0_bufvec *user)
Definition: io.c:230
M0_INTERNAL void m0_stob_io_fini(struct m0_stob_io *io)
Definition: io.c:122
#define NULL
Definition: misc.h:38
M0_INTERNAL void m0_clink_init(struct m0_clink *link, m0_chan_cb_t cb)
Definition: chan.c:201
Definition: io.h:230
M0_INTERNAL void m0_clink_del_lock(struct m0_clink *link)
Definition: chan.c:293
#define ergo(a, b)
Definition: misc.h:293
M0_INTERNAL void m0_stob_io_credit(const struct m0_stob_io *io, const struct m0_stob_domain *dom, struct m0_be_tx_credit *accum)
Definition: io.c:130
M0_INTERNAL bool m0_chan_has_waiters(struct m0_chan *chan)
Definition: chan.c:185
#define M0_LOG(level,...)
Definition: trace.h:167
M0_INTERNAL const struct m0_fid * m0_stob_domain_id_get(const struct m0_stob_domain *dom)
Definition: domain.c:300
struct m0_vec ov_vec
Definition: vec.h:147
#define M0_ADDB2_PUSH(id,...)
Definition: addb2.h:261
const struct m0_stob_io_op * si_op
Definition: io.h:328
uint64_t m0_bindex_t
Definition: types.h:80
struct m0_chan si_wait
Definition: io.h:318
uint64_t m0_bcount_t
Definition: types.h:77
M0_INTERNAL const struct m0_fid * m0_stob_fid_get(struct m0_stob *stob)
Definition: stob.c:255
#define M0_SET0(obj)
Definition: misc.h:64
M0_ADDB2_ADD(M0_AVI_FS_CREATE, new_fid.f_container, new_fid.f_key, mode, rc)
int(* sio_launch)(struct m0_stob_io *io)
Definition: io.h:439
void ** ov_buf
Definition: vec.h:149
static struct foo * obj
Definition: tlist.c:302
#define PRIx64
Definition: types.h:61
void(* sio_fini)(struct m0_stob_io *io)
Definition: io.h:430
Definition: sock.c:887
static m0_bcount_t count
Definition: xcode.c:167
struct m0_fid fid
Definition: di.c:46
struct m0_vec iv_vec
Definition: vec.h:139
return M0_RC(rc)
M0_INTERNAL uint32_t m0_stob_block_shift(struct m0_stob *stob)
Definition: stob.c:270
struct m0_bufvec si_user
Definition: io.h:300
#define M0_ENTRY(...)
Definition: trace.h:170
m0_bindex_t * iv_index
Definition: vec.h:141
M0_INTERNAL uint64_t m0_dummy_id_generate(void)
Definition: misc.c:425
int i
Definition: dir.c:1033
struct m0_dtx * si_tx
Definition: io.h:351
M0_INTERNAL int m0_stob_io_prepare_and_launch(struct m0_stob_io *io, struct m0_stob *obj, struct m0_dtx *tx, struct m0_io_scope *scope)
Definition: io.c:219
M0_INTERNAL const struct m0_stob_id * m0_stob_id_get(struct m0_stob *stob)
Definition: stob.c:250
Definition: stob.h:163
struct m0_indexvec si_stob
Definition: io.h:311
int32_t si_rc
Definition: io.h:334
static struct m0_stob * stob
Definition: storage.c:39
M0_INTERNAL void m0_chan_init(struct m0_chan *chan, struct m0_mutex *ch_guard)
Definition: chan.c:96
int(* sio_prepare)(struct m0_stob_io *io)
Definition: io.h:447
#define STOB_ID_P(si)
Definition: stob.h:109
m0_time_t m0_time_now(void)
Definition: time.c:134
static bool stob_io_invariant(struct m0_stob_io *io, struct m0_stob *obj, enum m0_stob_io_state state)
Definition: io.c:94
static struct m0_bufvec bvec
Definition: xcode.c:169
m0_time_t si_start
Definition: io.h:405
static struct m0_stob_domain * dom
Definition: storage.c:38
Definition: io.h:244
M0_INTERNAL void * m0_stob_addr_pack(const void *buf, uint32_t shift)
Definition: io.c:293
M0_INTERNAL int m0_stob_io_private_setup(struct m0_stob_io *io, struct m0_stob *obj)
Definition: io.c:49
uint32_t si_stob_magic
Definition: io.h:388
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
#define M0_POST(cond)
Definition: xcode.h:73
uint64_t si_id
Definition: io.h:406
uint32_t v_nr
Definition: vec.h:51
enum m0_stob_io_state si_state
Definition: io.h:345
Definition: io.h:255
static m0_bindex_t offset
Definition: dump.c:173
Definition: io.h:285
m0_bcount_t * v_count
Definition: vec.h:53
static struct m0_clink clink[RDWR_REQUEST_MAX]
#define FID_P(f)
Definition: fid.h:77
static struct m0_stob_io io
Definition: ad.c:59
void m0_addb2_pop(uint64_t id)
Definition: addb2.c:440
m0_bcount_t si_count
Definition: io.h:340
M0_INTERNAL m0_bcount_t m0_vec_count(const struct m0_vec *vec)
Definition: vec.c:53
struct m0_stob * si_obj
Definition: io.h:326
struct m0_mutex si_mutex
Definition: io.h:319
static void stob_io_fill(struct m0_stob_io *io, struct m0_stob *obj, struct m0_dtx *tx, struct m0_io_scope *scope, enum m0_stob_io_state state, bool count_update)
Definition: io.c:138
void m0_clink_add_lock(struct m0_chan *chan, struct m0_clink *link)
Definition: chan.c:255
#define PRIu32
Definition: types.h:66
M0_INTERNAL enum m0_stob_state m0_stob_state_get(struct m0_stob *stob)
Definition: stob.c:265
void * si_stob_private
Definition: io.h:367
Definition: fid.h:38
M0_INTERNAL void * m0_stob_addr_open(const void *buf, uint32_t shift)
Definition: io.c:302
static void stob_io_addb2_add_and_push(uint64_t id, struct m0_stob_io *io, struct m0_stob *obj)
Definition: io.c:66
M0_INTERNAL void m0_stob_iovec_sort(struct m0_stob_io *stob)
Definition: io.c:311
#define _0C(exp)
Definition: assert.h:311
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
M0_INTERNAL void m0_clink_fini(struct m0_clink *link)
Definition: chan.c:208
void(* sdo_stob_write_credit)(const struct m0_stob_domain *dom, const struct m0_stob_io *io, struct m0_be_tx_credit *accum)
Definition: domain.h:147
m0_stob_io_state
Definition: io.h:238
M0_INTERNAL void m0_stob_io_init(struct m0_stob_io *io)
Definition: io.c:111
const struct m0_stob_domain_ops * sd_ops
Definition: domain.h:94
#define M0_ASSERT_INFO(cond, fmt,...)
#define STOB_ID_F
Definition: stob.h:108
#define SWAP_NEXT(arr, idx)
M0_INTERNAL int m0_stob_io_launch(struct m0_stob_io *io, struct m0_stob *obj, struct m0_dtx *tx, struct m0_io_scope *scope)
Definition: io.c:192
Definition: io.h:229
M0_INTERNAL int m0_stob_io_prepare(struct m0_stob_io *io, struct m0_stob *obj, struct m0_dtx *tx, struct m0_io_scope *scope)
Definition: io.c:155
M0_INTERNAL void m0_chan_fini_lock(struct m0_chan *chan)
Definition: chan.c:112
struct m0_io_scope * si_scope
Definition: io.h:355
M0_INTERNAL uint8_t m0_stob_domain__type_id(const struct m0_fid *dom_id)
Definition: domain.c:317
int32_t rc
Definition: trigger_fop.h:47
M0_INTERNAL bool m0_stob_io_stob_is_valid(const struct m0_indexvec *stob)
Definition: io.c:235
#define FID_F
Definition: fid.h:75
Definition: vec.h:145
static void m0_stob_io_private_fini(struct m0_stob_io *io)
Definition: io.c:41
enum m0_stob_io_opcode si_opcode
Definition: io.h:286