Motr  M0
io_sched.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2015-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 
30 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_BE
31 #include "lib/trace.h"
32 
33 #include "be/io_sched.h"
34 
35 #include "lib/ext.h" /* m0_ext */
36 
37 #include "be/op.h" /* m0_be_op */
38 #include "be/io.h" /* m0_be_io_launch */
39 
40 #include "motr/magic.h" /* M0_BE_LOG_IO_MAGIC */
41 #include "stob/io.h" /* SIO_WRITE */
42 
43 
44 /* m0_be_io_sched::bis_ios */
45 M0_TL_DESCR_DEFINE(sched_io, "be log scheduler IOs", static,
46  struct m0_be_io, bio_sched_link, bio_sched_magic,
48 M0_TL_DEFINE(sched_io, static, struct m0_be_io);
49 
50 
51 M0_INTERNAL int m0_be_io_sched_init(struct m0_be_io_sched *sched,
52  struct m0_be_io_sched_cfg *cfg)
53 {
54  if (cfg != NULL)
55  sched->bis_cfg = *cfg;
56  m0_mutex_init(&sched->bis_lock);
57  sched_io_tlist_init(&sched->bis_ios);
58  sched->bis_io_in_progress = false;
59  sched->bis_pos = sched->bis_cfg.bisc_pos_start;
60 
61  return 0;
62 }
63 
64 M0_INTERNAL void m0_be_io_sched_fini(struct m0_be_io_sched *sched)
65 {
66  sched_io_tlist_fini(&sched->bis_ios);
67  m0_mutex_fini(&sched->bis_lock);
68 }
69 
70 M0_INTERNAL void m0_be_io_sched_lock(struct m0_be_io_sched *sched)
71 {
72  m0_mutex_lock(&sched->bis_lock);
73 }
74 
75 M0_INTERNAL void m0_be_io_sched_unlock(struct m0_be_io_sched *sched)
76 {
77  m0_mutex_unlock(&sched->bis_lock);
78 }
79 
80 M0_INTERNAL bool m0_be_io_sched_is_locked(struct m0_be_io_sched *sched)
81 {
82  return m0_mutex_is_locked(&sched->bis_lock);
83 }
84 
85 static bool be_io_sched_invariant(struct m0_be_io_sched *sched)
86 {
87  return m0_tl_forall(sched_io, io, &sched->bis_ios,
88  sched_io_tlist_next(&sched->bis_ios, io) == NULL ||
89  io->bio_ext.e_end <=
90  sched_io_tlist_next(&sched->bis_ios, io)->bio_ext.e_start);
91 }
92 
93 static void be_io_sched_launch_next(struct m0_be_io_sched *sched)
94 {
95  struct m0_be_io *io;
96 
98 
99  if (!sched->bis_io_in_progress) {
100  io = sched_io_tlist_head(&sched->bis_ios);
101  M0_ASSERT(ergo(io != NULL,
102  sched->bis_pos <= io->bio_ext.e_start));
103  if (io != NULL) {
104  M0_LOG(M0_DEBUG, "bis_pos=%" PRIu64 " "
105  "io->bio_ext.e_start=%"PRIu64,
106  sched->bis_pos, io->bio_ext.e_start);
107  }
108  if (io != NULL && io->bio_ext.e_start == sched->bis_pos) {
109  sched->bis_io_in_progress = true;
110  M0_LOG(M0_DEBUG, "sched=%p io=%p pos=%"PRId64,
111  sched, io, sched->bis_pos);
112  m0_be_op_active(io->bio_sched_op_user);
113  m0_be_io_launch(io, &io->bio_sched_op);
114  }
115  }
116 }
117 
119 {
120  m0_be_io_sched_lock(sched);
122  m0_be_io_sched_unlock(sched);
123 }
124 
125 static void be_io_sched_cb(struct m0_be_op *op, void *param)
126 {
127  struct m0_be_io *io = param;
128  struct m0_be_io_sched *sched = io->bio_sched;
129 
130  M0_LOG(M0_DEBUG, "sched=%p io=%p", sched, io);
131 
132  M0_PRE(io->bio_ext.e_start == sched->bis_pos);
133 
134  m0_be_io_sched_lock(sched);
135  sched_io_tlink_del_fini(io);
136  m0_be_op_fini(&io->bio_sched_op);
137  sched->bis_io_in_progress = false;
138  sched->bis_pos = io->bio_ext.e_end;
139  m0_be_io_sched_unlock(sched);
140 
141  m0_be_op_done(io->bio_sched_op_user);
143 }
144 
145 static void be_io_sched_insert(struct m0_be_io_sched *sched,
146  struct m0_be_io *io)
147 {
148  struct m0_be_io *io_prev;
149  struct m0_be_io *io_next;
150 
153 
154  for (io_prev = sched_io_tlist_tail(&sched->bis_ios);
155  io_prev != NULL;
156  io_prev = sched_io_tlist_prev(&sched->bis_ios, io_prev)) {
157  if (io_prev->bio_ext.e_end <= io->bio_ext.e_start)
158  break;
159  }
160  if (io_prev != NULL && m0_ext_is_empty(&io->bio_ext)) {
161  io_next = sched_io_tlist_next(&sched->bis_ios, io_prev);
162  while (io_next != NULL && m0_ext_is_empty(&io_next->bio_ext)) {
163  io_prev = io_next;
164  io_next = sched_io_tlist_next(&sched->bis_ios, io_prev);
165  }
166  }
167  sched_io_tlink_init(io);
168  if (io_prev == NULL)
169  sched_io_tlist_add(&sched->bis_ios, io);
170  else
171  sched_io_tlist_add_after(io_prev, io);
172 
174 }
175 
176 M0_INTERNAL void m0_be_io_sched_add(struct m0_be_io_sched *sched,
177  struct m0_be_io *io,
178  struct m0_ext *ext,
179  struct m0_be_op *op)
180 {
181  struct m0_be_io *io_last;
182 
183  M0_LOG(M0_DEBUG, "sched=%p io=%p op=%p ext="EXT_F" "
184  "m0_be_io_size(io)=%"PRIu64, sched, io, op,
185  EXT_P(ext == NULL ? &M0_EXT(0, 0) : ext), m0_be_io_size(io));
186 
189  ext == NULL));
190 
191  io->bio_sched = sched;
193  io_last = sched_io_tlist_tail(&sched->bis_ios);
194  io->bio_ext.e_start = io_last == NULL ? sched->bis_pos :
195  io_last->bio_ext.e_end;
196  io->bio_ext.e_end = io->bio_ext.e_start;
197  m0_ext_init(&io->bio_ext);
198  } else {
199  io->bio_ext = *ext;
200  }
201  be_io_sched_insert(sched, io);
202  M0_SET0(&io->bio_sched_op);
203  m0_be_op_init(&io->bio_sched_op);
204  m0_be_op_callback_set(&io->bio_sched_op, &be_io_sched_cb,
205  io, M0_BOS_GC);
206  io->bio_sched_op_user = op;
208 }
209 
210 #undef M0_TRACE_SUBSYSTEM
211 
213 /*
214  * Local variables:
215  * c-indentation-style: "K&R"
216  * c-basic-offset: 8
217  * tab-width: 8
218  * fill-column: 80
219  * scroll-step: 1
220  * End:
221  */
222 /*
223  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
224  */
#define M0_PRE(cond)
M0_INTERNAL m0_bcount_t m0_be_io_size(struct m0_be_io *bio)
Definition: io.c:500
m0_bcount_t bisc_pos_start
Definition: io_sched.h:44
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
m0_bindex_t e_end
Definition: ext.h:40
#define NULL
Definition: misc.h:38
#define ergo(a, b)
Definition: misc.h:293
#define M0_LOG(level,...)
Definition: trace.h:167
static void be_io_sched_insert(struct m0_be_io_sched *sched, struct m0_be_io *io)
Definition: io_sched.c:145
m0_bcount_t bis_pos
Definition: io_sched.h:71
M0_INTERNAL void m0_be_op_callback_set(struct m0_be_op *op, m0_be_op_cb_t cb, void *param, enum m0_be_op_state state)
Definition: op.c:239
#define M0_SET0(obj)
Definition: misc.h:64
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
static void be_io_sched_cb(struct m0_be_op *op, void *param)
Definition: io_sched.c:125
#define M0_EXT(start, end)
Definition: ext.h:55
static void be_io_sched_launch_next_locked(struct m0_be_io_sched *sched)
Definition: io_sched.c:118
op
Definition: libdemo.c:64
#define equi(a, b)
Definition: misc.h:297
#define PRIu64
Definition: types.h:58
M0_INTERNAL int m0_be_io_sched_init(struct m0_be_io_sched *sched, struct m0_be_io_sched_cfg *cfg)
Definition: io_sched.c:51
M0_INTERNAL bool m0_be_io_sched_is_locked(struct m0_be_io_sched *sched)
Definition: io_sched.c:80
#define M0_ASSERT(cond)
M0_INTERNAL bool m0_mutex_is_locked(const struct m0_mutex *mutex)
Definition: mutex.c:95
M0_INTERNAL void m0_ext_init(struct m0_ext *ext)
Definition: ext.c:32
M0_INTERNAL void m0_be_io_sched_lock(struct m0_be_io_sched *sched)
Definition: io_sched.c:70
struct m0_ext bio_ext
Definition: io.h:123
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
#define M0_POST(cond)
M0_INTERNAL void m0_be_io_sched_fini(struct m0_be_io_sched *sched)
Definition: io_sched.c:64
M0_INTERNAL void m0_be_op_done(struct m0_be_op *op)
Definition: stubs.c:104
static struct m0_stob_io io
Definition: ad.c:59
#define PRId64
Definition: types.h:57
#define EXT_P(x)
Definition: ext.h:86
M0_INTERNAL bool m0_ext_is_empty(const struct m0_ext *ext)
Definition: ext.c:76
M0_TL_DESCR_DEFINE(sched_io, "be log scheduler IOs", static, struct m0_be_io, bio_sched_link, bio_sched_magic, M0_BE_IO_SCHED_MAGIC, M0_BE_IO_SCHED_HEAD_MAGIC)
M0_INTERNAL bool m0_be_io_is_empty(struct m0_be_io *bio)
Definition: io.c:646
struct m0_mutex bis_lock
Definition: io_sched.h:68
#define EXT_F
Definition: ext.h:85
M0_INTERNAL void m0_be_op_active(struct m0_be_op *op)
Definition: stubs.c:100
M0_INTERNAL void m0_be_io_sched_unlock(struct m0_be_io_sched *sched)
Definition: io_sched.c:75
Definition: ext.h:37
Definition: op.h:64
M0_INTERNAL enum m0_stob_io_opcode m0_be_io_opcode(struct m0_be_io *io)
Definition: io.c:641
M0_INTERNAL void m0_be_op_fini(struct m0_be_op *op)
Definition: stubs.c:92
static bool be_io_sched_invariant(struct m0_be_io_sched *sched)
Definition: io_sched.c:85
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
M0_INTERNAL void m0_be_io_sched_add(struct m0_be_io_sched *sched, struct m0_be_io *io, struct m0_ext *ext, struct m0_be_op *op)
Definition: io_sched.c:176
bool bis_io_in_progress
Definition: io_sched.h:69
Definition: io.h:87
static void be_io_sched_launch_next(struct m0_be_io_sched *sched)
Definition: io_sched.c:93
struct m0_tl bis_ios
Definition: io_sched.h:67
Definition: io.h:229
Definition: op.h:74
M0_INTERNAL void m0_be_op_init(struct m0_be_op *op)
Definition: stubs.c:87
struct m0_be_io_sched_cfg bis_cfg
Definition: io_sched.h:65
M0_INTERNAL void m0_be_io_launch(struct m0_be_io *bio, struct m0_be_op *op)
Definition: io.c:599
#define m0_tl_forall(name, var, head,...)
Definition: tlist.h:735
M0_TL_DEFINE(sched_io, static, struct m0_be_io)