hc
2024-05-14 bedbef8ad3e75a304af6361af235302bcc61d06b
kernel/drivers/block/xen-blkback/xenbus.c
....@@ -1,16 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* Xenbus code for blkif backend
23 Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
34 Copyright (C) 2005 XenSource Ltd
45
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
146
157 */
168
....@@ -152,8 +144,7 @@
152144 INIT_LIST_HEAD(&ring->pending_free);
153145 INIT_LIST_HEAD(&ring->persistent_purge_list);
154146 INIT_WORK(&ring->persistent_purge_work, xen_blkbk_unmap_purged_grants);
155
- spin_lock_init(&ring->free_pages_lock);
156
- INIT_LIST_HEAD(&ring->free_pages);
147
+ gnttab_page_cache_init(&ring->free_pages);
157148
158149 spin_lock_init(&ring->pending_free_lock);
159150 init_waitqueue_head(&ring->pending_free_wq);
....@@ -165,6 +156,11 @@
165156
166157 return 0;
167158 }
159
+
160
+/* Enable the persistent grants feature. */
161
+static bool feature_persistent = true;
162
+module_param(feature_persistent, bool, 0644);
163
+MODULE_PARM_DESC(feature_persistent, "Enables the persistent grants feature");
168164
169165 static struct xen_blkif *xen_blkif_alloc(domid_t domid)
170166 {
....@@ -198,6 +194,9 @@
198194 {
199195 int err;
200196 struct xen_blkif *blkif = ring->blkif;
197
+ const struct blkif_common_sring *sring_common;
198
+ RING_IDX rsp_prod, req_prod;
199
+ unsigned int size;
201200
202201 /* Already connected through? */
203202 if (ring->irq)
....@@ -208,45 +207,61 @@
208207 if (err < 0)
209208 return err;
210209
210
+ sring_common = (struct blkif_common_sring *)ring->blk_ring;
211
+ rsp_prod = READ_ONCE(sring_common->rsp_prod);
212
+ req_prod = READ_ONCE(sring_common->req_prod);
213
+
211214 switch (blkif->blk_protocol) {
212215 case BLKIF_PROTOCOL_NATIVE:
213216 {
214
- struct blkif_sring *sring;
215
- sring = (struct blkif_sring *)ring->blk_ring;
216
- BACK_RING_INIT(&ring->blk_rings.native, sring,
217
- XEN_PAGE_SIZE * nr_grefs);
217
+ struct blkif_sring *sring_native =
218
+ (struct blkif_sring *)ring->blk_ring;
219
+
220
+ BACK_RING_ATTACH(&ring->blk_rings.native, sring_native,
221
+ rsp_prod, XEN_PAGE_SIZE * nr_grefs);
222
+ size = __RING_SIZE(sring_native, XEN_PAGE_SIZE * nr_grefs);
218223 break;
219224 }
220225 case BLKIF_PROTOCOL_X86_32:
221226 {
222
- struct blkif_x86_32_sring *sring_x86_32;
223
- sring_x86_32 = (struct blkif_x86_32_sring *)ring->blk_ring;
224
- BACK_RING_INIT(&ring->blk_rings.x86_32, sring_x86_32,
225
- XEN_PAGE_SIZE * nr_grefs);
227
+ struct blkif_x86_32_sring *sring_x86_32 =
228
+ (struct blkif_x86_32_sring *)ring->blk_ring;
229
+
230
+ BACK_RING_ATTACH(&ring->blk_rings.x86_32, sring_x86_32,
231
+ rsp_prod, XEN_PAGE_SIZE * nr_grefs);
232
+ size = __RING_SIZE(sring_x86_32, XEN_PAGE_SIZE * nr_grefs);
226233 break;
227234 }
228235 case BLKIF_PROTOCOL_X86_64:
229236 {
230
- struct blkif_x86_64_sring *sring_x86_64;
231
- sring_x86_64 = (struct blkif_x86_64_sring *)ring->blk_ring;
232
- BACK_RING_INIT(&ring->blk_rings.x86_64, sring_x86_64,
233
- XEN_PAGE_SIZE * nr_grefs);
237
+ struct blkif_x86_64_sring *sring_x86_64 =
238
+ (struct blkif_x86_64_sring *)ring->blk_ring;
239
+
240
+ BACK_RING_ATTACH(&ring->blk_rings.x86_64, sring_x86_64,
241
+ rsp_prod, XEN_PAGE_SIZE * nr_grefs);
242
+ size = __RING_SIZE(sring_x86_64, XEN_PAGE_SIZE * nr_grefs);
234243 break;
235244 }
236245 default:
237246 BUG();
238247 }
239248
249
+ err = -EIO;
250
+ if (req_prod - rsp_prod > size)
251
+ goto fail;
252
+
240253 err = bind_interdomain_evtchn_to_irqhandler_lateeoi(blkif->domid,
241254 evtchn, xen_blkif_be_int, 0, "blkif-backend", ring);
242
- if (err < 0) {
243
- xenbus_unmap_ring_vfree(blkif->be->dev, ring->blk_ring);
244
- ring->blk_rings.common.sring = NULL;
245
- return err;
246
- }
255
+ if (err < 0)
256
+ goto fail;
247257 ring->irq = err;
248258
249259 return 0;
260
+
261
+fail:
262
+ xenbus_unmap_ring_vfree(blkif->be->dev, ring->blk_ring);
263
+ ring->blk_rings.common.sring = NULL;
264
+ return err;
250265 }
251266
252267 static int xen_blkif_disconnect(struct xen_blkif *blkif)
....@@ -307,8 +322,7 @@
307322 BUG_ON(atomic_read(&ring->persistent_gnt_in_use) != 0);
308323 BUG_ON(!list_empty(&ring->persistent_purge_list));
309324 BUG_ON(!RB_EMPTY_ROOT(&ring->persistent_gnts));
310
- BUG_ON(!list_empty(&ring->free_pages));
311
- BUG_ON(ring->free_pages_num != 0);
325
+ BUG_ON(ring->free_pages.num_pages != 0);
312326 BUG_ON(ring->persistent_gnt_c != 0);
313327 WARN_ON(i != (XEN_BLKIF_REQS_PER_PAGE * blkif->nr_ring_pages));
314328 ring->active = false;
....@@ -349,6 +363,12 @@
349363 return -ENOMEM;
350364
351365 return 0;
366
+}
367
+
368
+void xen_blkif_interface_fini(void)
369
+{
370
+ kmem_cache_destroy(xen_blkif_cachep);
371
+ xen_blkif_cachep = NULL;
352372 }
353373
354374 /*
....@@ -450,7 +470,6 @@
450470 device_remove_file(&dev->dev, &dev_attr_physical_device);
451471 }
452472
453
-
454473 static void xen_vbd_free(struct xen_vbd *vbd)
455474 {
456475 if (vbd->bdev)
....@@ -507,6 +526,7 @@
507526 handle, blkif->domid);
508527 return 0;
509528 }
529
+
510530 static int xen_blkbk_remove(struct xenbus_device *dev)
511531 {
512532 struct backend_info *be = dev_get_drvdata(&dev->dev);
....@@ -590,6 +610,7 @@
590610 if (err)
591611 dev_warn(&dev->dev, "writing feature-discard (%d)", err);
592612 }
613
+
593614 int xen_blkbk_barrier(struct xenbus_transaction xbt,
594615 struct backend_info *be, int state)
595616 {
....@@ -674,7 +695,6 @@
674695 xen_blkbk_remove(dev);
675696 return err;
676697 }
677
-
678698
679699 /*
680700 * Callback received when the hotplug scripts have placed the physical-device
....@@ -767,7 +787,6 @@
767787 }
768788 }
769789
770
-
771790 /*
772791 * Callback received when the frontend's state changes.
773792 */
....@@ -828,7 +847,7 @@
828847 xenbus_switch_state(dev, XenbusStateClosed);
829848 if (xenbus_dev_is_online(dev))
830849 break;
831
- /* fall through */
850
+ fallthrough;
832851 /* if not online */
833852 case XenbusStateUnknown:
834853 /* implies xen_blkif_disconnect() via xen_blkbk_remove() */
....@@ -842,9 +861,27 @@
842861 }
843862 }
844863
864
+/* Once a memory pressure is detected, squeeze free page pools for a while. */
865
+static unsigned int buffer_squeeze_duration_ms = 10;
866
+module_param_named(buffer_squeeze_duration_ms,
867
+ buffer_squeeze_duration_ms, int, 0644);
868
+MODULE_PARM_DESC(buffer_squeeze_duration_ms,
869
+"Duration in ms to squeeze pages buffer when a memory pressure is detected");
870
+
871
+/*
872
+ * Callback received when the memory pressure is detected.
873
+ */
874
+static void reclaim_memory(struct xenbus_device *dev)
875
+{
876
+ struct backend_info *be = dev_get_drvdata(&dev->dev);
877
+
878
+ if (!be)
879
+ return;
880
+ be->blkif->buffer_squeeze_end = jiffies +
881
+ msecs_to_jiffies(buffer_squeeze_duration_ms);
882
+}
845883
846884 /* ** Connection ** */
847
-
848885
849886 /*
850887 * Write the physical details regarding the block device to the store, and
....@@ -873,7 +910,8 @@
873910
874911 xen_blkbk_barrier(xbt, be, be->blkif->vbd.flush_support);
875912
876
- err = xenbus_printf(xbt, dev->nodename, "feature-persistent", "%u", 1);
913
+ err = xenbus_printf(xbt, dev->nodename, "feature-persistent", "%u",
914
+ be->blkif->vbd.feature_gnt_persistent_parm);
877915 if (err) {
878916 xenbus_dev_fatal(dev, err, "writing %s/feature-persistent",
879917 dev->nodename);
....@@ -937,7 +975,7 @@
937975 int err, i, j;
938976 struct xen_blkif *blkif = ring->blkif;
939977 struct xenbus_device *dev = blkif->be->dev;
940
- unsigned int ring_page_order, nr_grefs, evtchn;
978
+ unsigned int nr_grefs, evtchn;
941979
942980 err = xenbus_scanf(XBT_NIL, dir, "event-channel", "%u",
943981 &evtchn);
....@@ -947,43 +985,33 @@
947985 return err;
948986 }
949987
950
- err = xenbus_scanf(XBT_NIL, dev->otherend, "ring-page-order", "%u",
951
- &ring_page_order);
952
- if (err != 1) {
953
- err = xenbus_scanf(XBT_NIL, dir, "ring-ref", "%u", &ring_ref[0]);
988
+ nr_grefs = blkif->nr_ring_pages;
989
+
990
+ if (unlikely(!nr_grefs)) {
991
+ WARN_ON(true);
992
+ return -EINVAL;
993
+ }
994
+
995
+ for (i = 0; i < nr_grefs; i++) {
996
+ char ring_ref_name[RINGREF_NAME_LEN];
997
+
998
+ if (blkif->multi_ref)
999
+ snprintf(ring_ref_name, RINGREF_NAME_LEN, "ring-ref%u", i);
1000
+ else {
1001
+ WARN_ON(i != 0);
1002
+ snprintf(ring_ref_name, RINGREF_NAME_LEN, "ring-ref");
1003
+ }
1004
+
1005
+ err = xenbus_scanf(XBT_NIL, dir, ring_ref_name,
1006
+ "%u", &ring_ref[i]);
1007
+
9541008 if (err != 1) {
9551009 err = -EINVAL;
956
- xenbus_dev_fatal(dev, err, "reading %s/ring-ref", dir);
1010
+ xenbus_dev_fatal(dev, err, "reading %s/%s",
1011
+ dir, ring_ref_name);
9571012 return err;
958
- }
959
- nr_grefs = 1;
960
- } else {
961
- unsigned int i;
962
-
963
- if (ring_page_order > xen_blkif_max_ring_order) {
964
- err = -EINVAL;
965
- xenbus_dev_fatal(dev, err, "%s/request %d ring page order exceed max:%d",
966
- dir, ring_page_order,
967
- xen_blkif_max_ring_order);
968
- return err;
969
- }
970
-
971
- nr_grefs = 1 << ring_page_order;
972
- for (i = 0; i < nr_grefs; i++) {
973
- char ring_ref_name[RINGREF_NAME_LEN];
974
-
975
- snprintf(ring_ref_name, RINGREF_NAME_LEN, "ring-ref%u", i);
976
- err = xenbus_scanf(XBT_NIL, dir, ring_ref_name,
977
- "%u", &ring_ref[i]);
978
- if (err != 1) {
979
- err = -EINVAL;
980
- xenbus_dev_fatal(dev, err, "reading %s/%s",
981
- dir, ring_ref_name);
982
- return err;
983
- }
9841013 }
9851014 }
986
- blkif->nr_ring_pages = nr_grefs;
9871015
9881016 err = -ENOMEM;
9891017 for (i = 0; i < nr_grefs * XEN_BLKIF_REQS_PER_PAGE; i++) {
....@@ -1034,35 +1062,39 @@
10341062 static int connect_ring(struct backend_info *be)
10351063 {
10361064 struct xenbus_device *dev = be->dev;
1037
- unsigned int pers_grants;
1065
+ struct xen_blkif *blkif = be->blkif;
10381066 char protocol[64] = "";
10391067 int err, i;
10401068 char *xspath;
10411069 size_t xspathsize;
10421070 const size_t xenstore_path_ext_size = 11; /* sufficient for "/queue-NNN" */
10431071 unsigned int requested_num_queues = 0;
1072
+ unsigned int ring_page_order;
10441073
10451074 pr_debug("%s %s\n", __func__, dev->otherend);
10461075
1047
- be->blkif->blk_protocol = BLKIF_PROTOCOL_DEFAULT;
1076
+ blkif->blk_protocol = BLKIF_PROTOCOL_DEFAULT;
10481077 err = xenbus_scanf(XBT_NIL, dev->otherend, "protocol",
10491078 "%63s", protocol);
10501079 if (err <= 0)
10511080 strcpy(protocol, "unspecified, assuming default");
10521081 else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE))
1053
- be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
1082
+ blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
10541083 else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32))
1055
- be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32;
1084
+ blkif->blk_protocol = BLKIF_PROTOCOL_X86_32;
10561085 else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64))
1057
- be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64;
1086
+ blkif->blk_protocol = BLKIF_PROTOCOL_X86_64;
10581087 else {
10591088 xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol);
10601089 return -ENOSYS;
10611090 }
1062
- pers_grants = xenbus_read_unsigned(dev->otherend, "feature-persistent",
1063
- 0);
1064
- be->blkif->vbd.feature_gnt_persistent = pers_grants;
1065
- be->blkif->vbd.overflow_max_grants = 0;
1091
+
1092
+ blkif->vbd.feature_gnt_persistent_parm = feature_persistent;
1093
+ blkif->vbd.feature_gnt_persistent =
1094
+ blkif->vbd.feature_gnt_persistent_parm &&
1095
+ xenbus_read_unsigned(dev->otherend, "feature-persistent", 0);
1096
+
1097
+ blkif->vbd.overflow_max_grants = 0;
10661098
10671099 /*
10681100 * Read the number of hardware queues from frontend.
....@@ -1078,16 +1110,33 @@
10781110 requested_num_queues, xenblk_max_queues);
10791111 return -ENOSYS;
10801112 }
1081
- be->blkif->nr_rings = requested_num_queues;
1082
- if (xen_blkif_alloc_rings(be->blkif))
1113
+ blkif->nr_rings = requested_num_queues;
1114
+ if (xen_blkif_alloc_rings(blkif))
10831115 return -ENOMEM;
10841116
10851117 pr_info("%s: using %d queues, protocol %d (%s) %s\n", dev->nodename,
1086
- be->blkif->nr_rings, be->blkif->blk_protocol, protocol,
1087
- pers_grants ? "persistent grants" : "");
1118
+ blkif->nr_rings, blkif->blk_protocol, protocol,
1119
+ blkif->vbd.feature_gnt_persistent ? "persistent grants" : "");
10881120
1089
- if (be->blkif->nr_rings == 1)
1090
- return read_per_ring_refs(&be->blkif->rings[0], dev->otherend);
1121
+ err = xenbus_scanf(XBT_NIL, dev->otherend, "ring-page-order", "%u",
1122
+ &ring_page_order);
1123
+ if (err != 1) {
1124
+ blkif->nr_ring_pages = 1;
1125
+ blkif->multi_ref = false;
1126
+ } else if (ring_page_order <= xen_blkif_max_ring_order) {
1127
+ blkif->nr_ring_pages = 1 << ring_page_order;
1128
+ blkif->multi_ref = true;
1129
+ } else {
1130
+ err = -EINVAL;
1131
+ xenbus_dev_fatal(dev, err,
1132
+ "requested ring page order %d exceed max:%d",
1133
+ ring_page_order,
1134
+ xen_blkif_max_ring_order);
1135
+ return err;
1136
+ }
1137
+
1138
+ if (blkif->nr_rings == 1)
1139
+ return read_per_ring_refs(&blkif->rings[0], dev->otherend);
10911140 else {
10921141 xspathsize = strlen(dev->otherend) + xenstore_path_ext_size;
10931142 xspath = kmalloc(xspathsize, GFP_KERNEL);
....@@ -1096,10 +1145,10 @@
10961145 return -ENOMEM;
10971146 }
10981147
1099
- for (i = 0; i < be->blkif->nr_rings; i++) {
1148
+ for (i = 0; i < blkif->nr_rings; i++) {
11001149 memset(xspath, 0, xspathsize);
11011150 snprintf(xspath, xspathsize, "%s/queue-%u", dev->otherend, i);
1102
- err = read_per_ring_refs(&be->blkif->rings[i], xspath);
1151
+ err = read_per_ring_refs(&blkif->rings[i], xspath);
11031152 if (err) {
11041153 kfree(xspath);
11051154 return err;
....@@ -1119,10 +1168,17 @@
11191168 .ids = xen_blkbk_ids,
11201169 .probe = xen_blkbk_probe,
11211170 .remove = xen_blkbk_remove,
1122
- .otherend_changed = frontend_changed
1171
+ .otherend_changed = frontend_changed,
1172
+ .allow_rebind = true,
1173
+ .reclaim_memory = reclaim_memory,
11231174 };
11241175
11251176 int xen_blkif_xenbus_init(void)
11261177 {
11271178 return xenbus_register_backend(&xen_blkbk_driver);
11281179 }
1180
+
1181
+void xen_blkif_xenbus_fini(void)
1182
+{
1183
+ xenbus_unregister_driver(&xen_blkbk_driver);
1184
+}