]> git.proxmox.com Git - zfsonlinux.git/blob - zfs-patches/0007-vdev_mirror-load-balancing-fixes.patch
buildsys: upload to pmg as well
[zfsonlinux.git] / zfs-patches / 0007-vdev_mirror-load-balancing-fixes.patch
1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Gvozden Neskovic <neskovic@gmail.com>
3 Date: Fri, 4 Aug 2017 11:29:56 +0200
4 Subject: [PATCH] vdev_mirror: load balancing fixes
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 vdev_queue:
10 - Track the last position of each vdev, including the io size,
11 in order to detect linear access of the following zio.
12 - Remove duplicate `vq_lastoffset`
13
14 vdev_mirror:
15 - Correctly calculate the zio offset (signedness issue)
16 - Deprecate `vdev_queue_register_lastoffset()`
17 - Add `VDEV_LABEL_START_SIZE` to zio offset of leaf vdevs
18
19 Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
20 Signed-off-by: Gvozden Neskovic <neskovic@gmail.com>
21 Closes #6461
22 (cherry picked from commit 06acbbc429bfe7197e5fc3a49acfeef5c37b64c8)
23 Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
24 ---
25 include/sys/vdev.h | 3 +--
26 include/sys/vdev_impl.h | 1 -
27 module/zfs/vdev_mirror.c | 36 ++++++++++++++++--------------------
28 module/zfs/vdev_queue.c | 21 +++++++--------------
29 4 files changed, 24 insertions(+), 37 deletions(-)
30
31 diff --git a/include/sys/vdev.h b/include/sys/vdev.h
32 index 7157ef43f..473d2691c 100644
33 --- a/include/sys/vdev.h
34 +++ b/include/sys/vdev.h
35 @@ -125,8 +125,7 @@ extern zio_t *vdev_queue_io(zio_t *zio);
36 extern void vdev_queue_io_done(zio_t *zio);
37
38 extern int vdev_queue_length(vdev_t *vd);
39 -extern uint64_t vdev_queue_lastoffset(vdev_t *vd);
40 -extern void vdev_queue_register_lastoffset(vdev_t *vd, zio_t *zio);
41 +extern uint64_t vdev_queue_last_offset(vdev_t *vd);
42
43 extern void vdev_config_dirty(vdev_t *vd);
44 extern void vdev_config_clean(vdev_t *vd);
45 diff --git a/include/sys/vdev_impl.h b/include/sys/vdev_impl.h
46 index 7c5e54b08..4c2e3cd2e 100644
47 --- a/include/sys/vdev_impl.h
48 +++ b/include/sys/vdev_impl.h
49 @@ -127,7 +127,6 @@ struct vdev_queue {
50 hrtime_t vq_io_delta_ts;
51 zio_t vq_io_search; /* used as local for stack reduction */
52 kmutex_t vq_lock;
53 - uint64_t vq_lastoffset;
54 };
55
56 /*
57 diff --git a/module/zfs/vdev_mirror.c b/module/zfs/vdev_mirror.c
58 index 0439e4b46..d230b4db4 100644
59 --- a/module/zfs/vdev_mirror.c
60 +++ b/module/zfs/vdev_mirror.c
61 @@ -116,7 +116,8 @@ static const zio_vsd_ops_t vdev_mirror_vsd_ops = {
62 static int
63 vdev_mirror_load(mirror_map_t *mm, vdev_t *vd, uint64_t zio_offset)
64 {
65 - uint64_t lastoffset;
66 + uint64_t last_offset;
67 + int64_t offset_diff;
68 int load;
69
70 /* All DVAs have equal weight at the root. */
71 @@ -129,13 +130,17 @@ vdev_mirror_load(mirror_map_t *mm, vdev_t *vd, uint64_t zio_offset)
72 * worse overall when resilvering with compared to without.
73 */
74
75 + /* Fix zio_offset for leaf vdevs */
76 + if (vd->vdev_ops->vdev_op_leaf)
77 + zio_offset += VDEV_LABEL_START_SIZE;
78 +
79 /* Standard load based on pending queue length. */
80 load = vdev_queue_length(vd);
81 - lastoffset = vdev_queue_lastoffset(vd);
82 + last_offset = vdev_queue_last_offset(vd);
83
84 if (vd->vdev_nonrot) {
85 /* Non-rotating media. */
86 - if (lastoffset == zio_offset)
87 + if (last_offset == zio_offset)
88 return (load + zfs_vdev_mirror_non_rotating_inc);
89
90 /*
91 @@ -148,16 +153,16 @@ vdev_mirror_load(mirror_map_t *mm, vdev_t *vd, uint64_t zio_offset)
92 }
93
94 /* Rotating media I/O's which directly follow the last I/O. */
95 - if (lastoffset == zio_offset)
96 + if (last_offset == zio_offset)
97 return (load + zfs_vdev_mirror_rotating_inc);
98
99 /*
100 * Apply half the seek increment to I/O's within seek offset
101 - * of the last I/O queued to this vdev as they should incur less
102 + * of the last I/O issued to this vdev as they should incur less
103 * of a seek increment.
104 */
105 - if (ABS(lastoffset - zio_offset) <
106 - zfs_vdev_mirror_rotating_seek_offset)
107 + offset_diff = (int64_t)(last_offset - zio_offset);
108 + if (ABS(offset_diff) < zfs_vdev_mirror_rotating_seek_offset)
109 return (load + (zfs_vdev_mirror_rotating_seek_inc / 2));
110
111 /* Apply the full seek increment to all other I/O's. */
112 @@ -382,29 +387,20 @@ vdev_mirror_child_select(zio_t *zio)
113 mm->mm_preferred_cnt++;
114 }
115
116 - if (mm->mm_preferred_cnt == 1) {
117 - vdev_queue_register_lastoffset(
118 - mm->mm_child[mm->mm_preferred[0]].mc_vd, zio);
119 + if (mm->mm_preferred_cnt == 1)
120 return (mm->mm_preferred[0]);
121 - }
122
123 - if (mm->mm_preferred_cnt > 1) {
124 - int c = vdev_mirror_preferred_child_randomize(zio);
125
126 - vdev_queue_register_lastoffset(mm->mm_child[c].mc_vd, zio);
127 - return (c);
128 - }
129 + if (mm->mm_preferred_cnt > 1)
130 + return (vdev_mirror_preferred_child_randomize(zio));
131
132 /*
133 * Every device is either missing or has this txg in its DTL.
134 * Look for any child we haven't already tried before giving up.
135 */
136 for (c = 0; c < mm->mm_children; c++) {
137 - if (!mm->mm_child[c].mc_tried) {
138 - vdev_queue_register_lastoffset(mm->mm_child[c].mc_vd,
139 - zio);
140 + if (!mm->mm_child[c].mc_tried)
141 return (c);
142 - }
143 }
144
145 /*
146 diff --git a/module/zfs/vdev_queue.c b/module/zfs/vdev_queue.c
147 index 6b3e87291..40cba340a 100644
148 --- a/module/zfs/vdev_queue.c
149 +++ b/module/zfs/vdev_queue.c
150 @@ -393,7 +393,7 @@ vdev_queue_init(vdev_t *vd)
151 sizeof (zio_t), offsetof(struct zio, io_queue_node));
152 }
153
154 - vq->vq_lastoffset = 0;
155 + vq->vq_last_offset = 0;
156 }
157
158 void
159 @@ -699,9 +699,8 @@ again:
160 */
161 tree = vdev_queue_class_tree(vq, p);
162 vq->vq_io_search.io_timestamp = 0;
163 - vq->vq_io_search.io_offset = vq->vq_last_offset + 1;
164 - VERIFY3P(avl_find(tree, &vq->vq_io_search,
165 - &idx), ==, NULL);
166 + vq->vq_io_search.io_offset = vq->vq_last_offset - 1;
167 + VERIFY3P(avl_find(tree, &vq->vq_io_search, &idx), ==, NULL);
168 zio = avl_nearest(tree, idx, AVL_AFTER);
169 if (zio == NULL)
170 zio = avl_first(tree);
171 @@ -728,7 +727,7 @@ again:
172 }
173
174 vdev_queue_pending_add(vq, zio);
175 - vq->vq_last_offset = zio->io_offset;
176 + vq->vq_last_offset = zio->io_offset + zio->io_size;
177
178 return (zio);
179 }
180 @@ -806,7 +805,7 @@ vdev_queue_io_done(zio_t *zio)
181 }
182
183 /*
184 - * As these three methods are only used for load calculations we're not
185 + * As these two methods are only used for load calculations we're not
186 * concerned if we get an incorrect value on 32bit platforms due to lack of
187 * vq_lock mutex use here, instead we prefer to keep it lock free for
188 * performance.
189 @@ -818,15 +817,9 @@ vdev_queue_length(vdev_t *vd)
190 }
191
192 uint64_t
193 -vdev_queue_lastoffset(vdev_t *vd)
194 +vdev_queue_last_offset(vdev_t *vd)
195 {
196 - return (vd->vdev_queue.vq_lastoffset);
197 -}
198 -
199 -void
200 -vdev_queue_register_lastoffset(vdev_t *vd, zio_t *zio)
201 -{
202 - vd->vdev_queue.vq_lastoffset = zio->io_offset + zio->io_size;
203 + return (vd->vdev_queue.vq_last_offset);
204 }
205
206 #if defined(_KERNEL) && defined(HAVE_SPL)
207 --
208 2.14.2
209