diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-16 15:36:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-16 15:36:39 -0400 |
commit | 11efae3506d882a8782bc89493a32e467defd6b9 (patch) | |
tree | 4671e72e14bb5f03e484ade6526ccfd1a40f75b8 | |
parent | 465c209db83e2cdaeb4a52f4e107a9fc636704db (diff) | |
parent | f6d85f04e29859dd3ea65395c05925da352dae89 (diff) |
Merge tag 'for-5.1/block-post-20190315' of git://git.kernel.dk/linux-block
Pull more block layer changes from Jens Axboe:
"This is a collection of both stragglers, and fixes that came in after
I finalized the initial pull. This contains:
- An MD pull request from Song, with a few minor fixes
- Set of NVMe patches via Christoph
- Pull request from Konrad, with a few fixes for xen/blkback
- pblk fix IO calculation fix (Javier)
- Segment calculation fix for pass-through (Ming)
- Fallthrough annotation for blkcg (Mathieu)"
* tag 'for-5.1/block-post-20190315' of git://git.kernel.dk/linux-block: (25 commits)
blkcg: annotate implicit fall through
nvme-tcp: support C2HData with SUCCESS flag
nvmet: ignore EOPNOTSUPP for discard
nvme: add proper write zeroes setup for the multipath device
nvme: add proper discard setup for the multipath device
nvme: remove nvme_ns_config_oncs
nvme: disable Write Zeroes for qemu controllers
nvmet-fc: bring Disconnect into compliance with FC-NVME spec
nvmet-fc: fix issues with targetport assoc_list list walking
nvme-fc: reject reconnect if io queue count is reduced to zero
nvme-fc: fix numa_node when dev is null
nvme-fc: use nr_phys_segments to determine existence of sgl
nvme-loop: init nvmet_ctrl fatal_err_work when allocate
nvme: update comment to make the code easier to read
nvme: put ns_head ref if namespace fails allocation
nvme-trace: fix cdw10 buffer overrun
nvme: don't warn on block content change effects
nvme: add get-feature to admin cmds tracer
md: Fix failed allocation of md_register_thread
It's wrong to add len to sector_nr in raid10 reshape twice
...
-rw-r--r-- | Documentation/admin-guide/md.rst | 3 | ||||
-rw-r--r-- | block/blk-merge.c | 15 | ||||
-rw-r--r-- | drivers/block/xen-blkback/xenbus.c | 99 | ||||
-rw-r--r-- | drivers/lightnvm/pblk-rl.c | 7 | ||||
-rw-r--r-- | drivers/md/raid10.c | 3 | ||||
-rw-r--r-- | drivers/md/raid5-log.h | 1 | ||||
-rw-r--r-- | drivers/md/raid5-ppl.c | 63 | ||||
-rw-r--r-- | drivers/md/raid5.c | 3 | ||||
-rw-r--r-- | drivers/nvme/host/core.c | 28 | ||||
-rw-r--r-- | drivers/nvme/host/fc.c | 36 | ||||
-rw-r--r-- | drivers/nvme/host/nvme.h | 5 | ||||
-rw-r--r-- | drivers/nvme/host/pci.c | 3 | ||||
-rw-r--r-- | drivers/nvme/host/tcp.c | 32 | ||||
-rw-r--r-- | drivers/nvme/host/trace.c | 14 | ||||
-rw-r--r-- | drivers/nvme/host/trace.h | 2 | ||||
-rw-r--r-- | drivers/nvme/target/core.c | 20 | ||||
-rw-r--r-- | drivers/nvme/target/fc.c | 42 | ||||
-rw-r--r-- | drivers/nvme/target/io-cmd-bdev.c | 8 | ||||
-rw-r--r-- | drivers/nvme/target/io-cmd-file.c | 2 | ||||
-rw-r--r-- | kernel/trace/blktrace.c | 1 |
20 files changed, 259 insertions, 128 deletions
diff --git a/Documentation/admin-guide/md.rst b/Documentation/admin-guide/md.rst index 84de718f24a4..3c51084ffd37 100644 --- a/Documentation/admin-guide/md.rst +++ b/Documentation/admin-guide/md.rst | |||
@@ -756,3 +756,6 @@ These currently include: | |||
756 | The cache mode for raid5. raid5 could include an extra disk for | 756 | The cache mode for raid5. raid5 could include an extra disk for |
757 | caching. The mode can be "write-throuth" and "write-back". The | 757 | caching. The mode can be "write-throuth" and "write-back". The |
758 | default is "write-through". | 758 | default is "write-through". |
759 | |||
760 | ppl_write_hint | ||
761 | NVMe stream ID to be set for each PPL write request. | ||
diff --git a/block/blk-merge.c b/block/blk-merge.c index 22467f475ab4..1c9d4f0f96ea 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c | |||
@@ -180,7 +180,7 @@ static unsigned get_max_segment_size(struct request_queue *q, | |||
180 | */ | 180 | */ |
181 | static bool bvec_split_segs(struct request_queue *q, struct bio_vec *bv, | 181 | static bool bvec_split_segs(struct request_queue *q, struct bio_vec *bv, |
182 | unsigned *nsegs, unsigned *last_seg_size, | 182 | unsigned *nsegs, unsigned *last_seg_size, |
183 | unsigned *front_seg_size, unsigned *sectors) | 183 | unsigned *front_seg_size, unsigned *sectors, unsigned max_segs) |
184 | { | 184 | { |
185 | unsigned len = bv->bv_len; | 185 | unsigned len = bv->bv_len; |
186 | unsigned total_len = 0; | 186 | unsigned total_len = 0; |
@@ -190,7 +190,7 @@ static bool bvec_split_segs(struct request_queue *q, struct bio_vec *bv, | |||
190 | * Multi-page bvec may be too big to hold in one segment, so the | 190 | * Multi-page bvec may be too big to hold in one segment, so the |
191 | * current bvec has to be splitted as multiple segments. | 191 | * current bvec has to be splitted as multiple segments. |
192 | */ | 192 | */ |
193 | while (len && new_nsegs + *nsegs < queue_max_segments(q)) { | 193 | while (len && new_nsegs + *nsegs < max_segs) { |
194 | seg_size = get_max_segment_size(q, bv->bv_offset + total_len); | 194 | seg_size = get_max_segment_size(q, bv->bv_offset + total_len); |
195 | seg_size = min(seg_size, len); | 195 | seg_size = min(seg_size, len); |
196 | 196 | ||
@@ -240,6 +240,7 @@ static struct bio *blk_bio_segment_split(struct request_queue *q, | |||
240 | bool do_split = true; | 240 | bool do_split = true; |
241 | struct bio *new = NULL; | 241 | struct bio *new = NULL; |
242 | const unsigned max_sectors = get_max_io_size(q, bio); | 242 | const unsigned max_sectors = get_max_io_size(q, bio); |
243 | const unsigned max_segs = queue_max_segments(q); | ||
243 | 244 | ||
244 | bio_for_each_bvec(bv, bio, iter) { | 245 | bio_for_each_bvec(bv, bio, iter) { |
245 | /* | 246 | /* |
@@ -254,14 +255,14 @@ static struct bio *blk_bio_segment_split(struct request_queue *q, | |||
254 | * Consider this a new segment if we're splitting in | 255 | * Consider this a new segment if we're splitting in |
255 | * the middle of this vector. | 256 | * the middle of this vector. |
256 | */ | 257 | */ |
257 | if (nsegs < queue_max_segments(q) && | 258 | if (nsegs < max_segs && |
258 | sectors < max_sectors) { | 259 | sectors < max_sectors) { |
259 | /* split in the middle of bvec */ | 260 | /* split in the middle of bvec */ |
260 | bv.bv_len = (max_sectors - sectors) << 9; | 261 | bv.bv_len = (max_sectors - sectors) << 9; |
261 | bvec_split_segs(q, &bv, &nsegs, | 262 | bvec_split_segs(q, &bv, &nsegs, |
262 | &seg_size, | 263 | &seg_size, |
263 | &front_seg_size, | 264 | &front_seg_size, |
264 | §ors); | 265 | §ors, max_segs); |
265 | } | 266 | } |
266 | goto split; | 267 | goto split; |
267 | } | 268 | } |
@@ -283,7 +284,7 @@ static struct bio *blk_bio_segment_split(struct request_queue *q, | |||
283 | continue; | 284 | continue; |
284 | } | 285 | } |
285 | new_segment: | 286 | new_segment: |
286 | if (nsegs == queue_max_segments(q)) | 287 | if (nsegs == max_segs) |
287 | goto split; | 288 | goto split; |
288 | 289 | ||
289 | bvprv = bv; | 290 | bvprv = bv; |
@@ -296,7 +297,7 @@ new_segment: | |||
296 | if (nsegs == 1 && seg_size > front_seg_size) | 297 | if (nsegs == 1 && seg_size > front_seg_size) |
297 | front_seg_size = seg_size; | 298 | front_seg_size = seg_size; |
298 | } else if (bvec_split_segs(q, &bv, &nsegs, &seg_size, | 299 | } else if (bvec_split_segs(q, &bv, &nsegs, &seg_size, |
299 | &front_seg_size, §ors)) { | 300 | &front_seg_size, §ors, max_segs)) { |
300 | goto split; | 301 | goto split; |
301 | } | 302 | } |
302 | } | 303 | } |
@@ -415,7 +416,7 @@ new_segment: | |||
415 | bvprv = bv; | 416 | bvprv = bv; |
416 | prev = 1; | 417 | prev = 1; |
417 | bvec_split_segs(q, &bv, &nr_phys_segs, &seg_size, | 418 | bvec_split_segs(q, &bv, &nr_phys_segs, &seg_size, |
418 | &front_seg_size, NULL); | 419 | &front_seg_size, NULL, UINT_MAX); |
419 | } | 420 | } |
420 | bbio = bio; | 421 | bbio = bio; |
421 | } | 422 | } |
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index a4bc74e72c39..24896ffb04ed 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c | |||
@@ -926,7 +926,7 @@ static int read_per_ring_refs(struct xen_blkif_ring *ring, const char *dir) | |||
926 | int err, i, j; | 926 | int err, i, j; |
927 | struct xen_blkif *blkif = ring->blkif; | 927 | struct xen_blkif *blkif = ring->blkif; |
928 | struct xenbus_device *dev = blkif->be->dev; | 928 | struct xenbus_device *dev = blkif->be->dev; |
929 | unsigned int ring_page_order, nr_grefs, evtchn; | 929 | unsigned int nr_grefs, evtchn; |
930 | 930 | ||
931 | err = xenbus_scanf(XBT_NIL, dir, "event-channel", "%u", | 931 | err = xenbus_scanf(XBT_NIL, dir, "event-channel", "%u", |
932 | &evtchn); | 932 | &evtchn); |
@@ -936,43 +936,42 @@ static int read_per_ring_refs(struct xen_blkif_ring *ring, const char *dir) | |||
936 | return err; | 936 | return err; |
937 | } | 937 | } |
938 | 938 | ||
939 | err = xenbus_scanf(XBT_NIL, dev->otherend, "ring-page-order", "%u", | 939 | nr_grefs = blkif->nr_ring_pages; |
940 | &ring_page_order); | 940 | |
941 | if (err != 1) { | 941 | if (unlikely(!nr_grefs)) { |
942 | err = xenbus_scanf(XBT_NIL, dir, "ring-ref", "%u", &ring_ref[0]); | 942 | WARN_ON(true); |
943 | return -EINVAL; | ||
944 | } | ||
945 | |||
946 | for (i = 0; i < nr_grefs; i++) { | ||
947 | char ring_ref_name[RINGREF_NAME_LEN]; | ||
948 | |||
949 | snprintf(ring_ref_name, RINGREF_NAME_LEN, "ring-ref%u", i); | ||
950 | err = xenbus_scanf(XBT_NIL, dir, ring_ref_name, | ||
951 | "%u", &ring_ref[i]); | ||
952 | |||
943 | if (err != 1) { | 953 | if (err != 1) { |
954 | if (nr_grefs == 1) | ||
955 | break; | ||
956 | |||
944 | err = -EINVAL; | 957 | err = -EINVAL; |
945 | xenbus_dev_fatal(dev, err, "reading %s/ring-ref", dir); | 958 | xenbus_dev_fatal(dev, err, "reading %s/%s", |
959 | dir, ring_ref_name); | ||
946 | return err; | 960 | return err; |
947 | } | 961 | } |
948 | nr_grefs = 1; | 962 | } |
949 | } else { | ||
950 | unsigned int i; | ||
951 | 963 | ||
952 | if (ring_page_order > xen_blkif_max_ring_order) { | 964 | if (err != 1) { |
965 | WARN_ON(nr_grefs != 1); | ||
966 | |||
967 | err = xenbus_scanf(XBT_NIL, dir, "ring-ref", "%u", | ||
968 | &ring_ref[0]); | ||
969 | if (err != 1) { | ||
953 | err = -EINVAL; | 970 | err = -EINVAL; |
954 | xenbus_dev_fatal(dev, err, "%s/request %d ring page order exceed max:%d", | 971 | xenbus_dev_fatal(dev, err, "reading %s/ring-ref", dir); |
955 | dir, ring_page_order, | ||
956 | xen_blkif_max_ring_order); | ||
957 | return err; | 972 | return err; |
958 | } | 973 | } |
959 | |||
960 | nr_grefs = 1 << ring_page_order; | ||
961 | for (i = 0; i < nr_grefs; i++) { | ||
962 | char ring_ref_name[RINGREF_NAME_LEN]; | ||
963 | |||
964 | snprintf(ring_ref_name, RINGREF_NAME_LEN, "ring-ref%u", i); | ||
965 | err = xenbus_scanf(XBT_NIL, dir, ring_ref_name, | ||
966 | "%u", &ring_ref[i]); | ||
967 | if (err != 1) { | ||
968 | err = -EINVAL; | ||
969 | xenbus_dev_fatal(dev, err, "reading %s/%s", | ||
970 | dir, ring_ref_name); | ||
971 | return err; | ||
972 | } | ||
973 | } | ||
974 | } | 974 | } |
975 | blkif->nr_ring_pages = nr_grefs; | ||
976 | 975 | ||
977 | for (i = 0; i < nr_grefs * XEN_BLKIF_REQS_PER_PAGE; i++) { | 976 | for (i = 0; i < nr_grefs * XEN_BLKIF_REQS_PER_PAGE; i++) { |
978 | req = kzalloc(sizeof(*req), GFP_KERNEL); | 977 | req = kzalloc(sizeof(*req), GFP_KERNEL); |
@@ -1023,6 +1022,7 @@ fail: | |||
1023 | static int connect_ring(struct backend_info *be) | 1022 | static int connect_ring(struct backend_info *be) |
1024 | { | 1023 | { |
1025 | struct xenbus_device *dev = be->dev; | 1024 | struct xenbus_device *dev = be->dev; |
1025 | struct xen_blkif *blkif = be->blkif; | ||
1026 | unsigned int pers_grants; | 1026 | unsigned int pers_grants; |
1027 | char protocol[64] = ""; | 1027 | char protocol[64] = ""; |
1028 | int err, i; | 1028 | int err, i; |
@@ -1030,28 +1030,29 @@ static int connect_ring(struct backend_info *be) | |||
1030 | size_t xspathsize; | 1030 | size_t xspathsize; |
1031 | const size_t xenstore_path_ext_size = 11; /* sufficient for "/queue-NNN" */ | 1031 | const size_t xenstore_path_ext_size = 11; /* sufficient for "/queue-NNN" */ |
1032 | unsigned int requested_num_queues = 0; | 1032 | unsigned int requested_num_queues = 0; |
1033 | unsigned int ring_page_order; | ||
1033 | 1034 | ||
1034 | pr_debug("%s %s\n", __func__, dev->otherend); | 1035 | pr_debug("%s %s\n", __func__, dev->otherend); |
1035 | 1036 | ||
1036 | be->blkif->blk_protocol = BLKIF_PROTOCOL_DEFAULT; | 1037 | blkif->blk_protocol = BLKIF_PROTOCOL_DEFAULT; |
1037 | err = xenbus_scanf(XBT_NIL, dev->otherend, "protocol", | 1038 | err = xenbus_scanf(XBT_NIL, dev->otherend, "protocol", |
1038 | "%63s", protocol); | 1039 | "%63s", protocol); |
1039 | if (err <= 0) | 1040 | if (err <= 0) |
1040 | strcpy(protocol, "unspecified, assuming default"); | 1041 | strcpy(protocol, "unspecified, assuming default"); |
1041 | else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE)) | 1042 | else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE)) |
1042 | be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE; | 1043 | blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE; |
1043 | else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32)) | 1044 | else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32)) |
1044 | be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32; | 1045 | blkif->blk_protocol = BLKIF_PROTOCOL_X86_32; |
1045 | else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64)) | 1046 | else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64)) |
1046 | be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64; | 1047 | blkif->blk_protocol = BLKIF_PROTOCOL_X86_64; |
1047 | else { | 1048 | else { |
1048 | xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol); | 1049 | xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol); |
1049 | return -ENOSYS; | 1050 | return -ENOSYS; |
1050 | } | 1051 | } |
1051 | pers_grants = xenbus_read_unsigned(dev->otherend, "feature-persistent", | 1052 | pers_grants = xenbus_read_unsigned(dev->otherend, "feature-persistent", |
1052 | 0); | 1053 | 0); |
1053 | be->blkif->vbd.feature_gnt_persistent = pers_grants; | 1054 | blkif->vbd.feature_gnt_persistent = pers_grants; |
1054 | be->blkif->vbd.overflow_max_grants = 0; | 1055 | blkif->vbd.overflow_max_grants = 0; |
1055 | 1056 | ||
1056 | /* | 1057 | /* |
1057 | * Read the number of hardware queues from frontend. | 1058 | * Read the number of hardware queues from frontend. |
@@ -1067,16 +1068,30 @@ static int connect_ring(struct backend_info *be) | |||
1067 | requested_num_queues, xenblk_max_queues); | 1068 | requested_num_queues, xenblk_max_queues); |
1068 | return -ENOSYS; | 1069 | return -ENOSYS; |
1069 | } | 1070 | } |
1070 | be->blkif->nr_rings = requested_num_queues; | 1071 | blkif->nr_rings = requested_num_queues; |
1071 | if (xen_blkif_alloc_rings(be->blkif)) | 1072 | if (xen_blkif_alloc_rings(blkif)) |
1072 | return -ENOMEM; | 1073 | return -ENOMEM; |
1073 | 1074 | ||
1074 | pr_info("%s: using %d queues, protocol %d (%s) %s\n", dev->nodename, | 1075 | pr_info("%s: using %d queues, protocol %d (%s) %s\n", dev->nodename, |
1075 | be->blkif->nr_rings, be->blkif->blk_protocol, protocol, | 1076 | blkif->nr_rings, blkif->blk_protocol, protocol, |
1076 | pers_grants ? "persistent grants" : ""); | 1077 | pers_grants ? "persistent grants" : ""); |
1077 | 1078 | ||
1078 | if (be->blkif->nr_rings == 1) | 1079 | ring_page_order = xenbus_read_unsigned(dev->otherend, |
1079 | return read_per_ring_refs(&be->blkif->rings[0], dev->otherend); | 1080 | "ring-page-order", 0); |
1081 | |||
1082 | if (ring_page_order > xen_blkif_max_ring_order) { | ||
1083 | err = -EINVAL; | ||
1084 | xenbus_dev_fatal(dev, err, | ||
1085 | "requested ring page order %d exceed max:%d", | ||
1086 | ring_page_order, | ||
1087 | xen_blkif_max_ring_order); | ||
1088 | return err; | ||
1089 | } | ||
1090 | |||
1091 | blkif->nr_ring_pages = 1 << ring_page_order; | ||
1092 | |||
1093 | if (blkif->nr_rings == 1) | ||
1094 | return read_per_ring_refs(&blkif->rings[0], dev->otherend); | ||
1080 | else { | 1095 | else { |
1081 | xspathsize = strlen(dev->otherend) + xenstore_path_ext_size; | 1096 | xspathsize = strlen(dev->otherend) + xenstore_path_ext_size; |
1082 | xspath = kmalloc(xspathsize, GFP_KERNEL); | 1097 | xspath = kmalloc(xspathsize, GFP_KERNEL); |
@@ -1085,10 +1100,10 @@ static int connect_ring(struct backend_info *be) | |||
1085 | return -ENOMEM; | 1100 | return -ENOMEM; |
1086 | } | 1101 | } |
1087 | 1102 | ||
1088 | for (i = 0; i < be->blkif->nr_rings; i++) { | 1103 | for (i = 0; i < blkif->nr_rings; i++) { |
1089 | memset(xspath, 0, xspathsize); | 1104 | memset(xspath, 0, xspathsize); |
1090 | snprintf(xspath, xspathsize, "%s/queue-%u", dev->otherend, i); | 1105 | snprintf(xspath, xspathsize, "%s/queue-%u", dev->otherend, i); |
1091 | err = read_per_ring_refs(&be->blkif->rings[i], xspath); | 1106 | err = read_per_ring_refs(&blkif->rings[i], xspath); |
1092 | if (err) { | 1107 | if (err) { |
1093 | kfree(xspath); | 1108 | kfree(xspath); |
1094 | return err; | 1109 | return err; |
diff --git a/drivers/lightnvm/pblk-rl.c b/drivers/lightnvm/pblk-rl.c index b014957dde0b..a5f8bc2defbc 100644 --- a/drivers/lightnvm/pblk-rl.c +++ b/drivers/lightnvm/pblk-rl.c | |||
@@ -233,10 +233,15 @@ void pblk_rl_init(struct pblk_rl *rl, int budget, int threshold) | |||
233 | /* To start with, all buffer is available to user I/O writers */ | 233 | /* To start with, all buffer is available to user I/O writers */ |
234 | rl->rb_budget = budget; | 234 | rl->rb_budget = budget; |
235 | rl->rb_user_max = budget; | 235 | rl->rb_user_max = budget; |
236 | rl->rb_max_io = threshold ? (budget - threshold) : (budget - 1); | ||
237 | rl->rb_gc_max = 0; | 236 | rl->rb_gc_max = 0; |
238 | rl->rb_state = PBLK_RL_HIGH; | 237 | rl->rb_state = PBLK_RL_HIGH; |
239 | 238 | ||
239 | /* Maximize I/O size and ansure that back threshold is respected */ | ||
240 | if (threshold) | ||
241 | rl->rb_max_io = budget - pblk->min_write_pgs_data - threshold; | ||
242 | else | ||
243 | rl->rb_max_io = budget - pblk->min_write_pgs_data - 1; | ||
244 | |||
240 | atomic_set(&rl->rb_user_cnt, 0); | 245 | atomic_set(&rl->rb_user_cnt, 0); |
241 | atomic_set(&rl->rb_gc_cnt, 0); | 246 | atomic_set(&rl->rb_gc_cnt, 0); |
242 | atomic_set(&rl->rb_space, -1); | 247 | atomic_set(&rl->rb_space, -1); |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index abb5d382f64d..3b6880dd648d 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -3939,6 +3939,8 @@ static int raid10_run(struct mddev *mddev) | |||
3939 | set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); | 3939 | set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); |
3940 | mddev->sync_thread = md_register_thread(md_do_sync, mddev, | 3940 | mddev->sync_thread = md_register_thread(md_do_sync, mddev, |
3941 | "reshape"); | 3941 | "reshape"); |
3942 | if (!mddev->sync_thread) | ||
3943 | goto out_free_conf; | ||
3942 | } | 3944 | } |
3943 | 3945 | ||
3944 | return 0; | 3946 | return 0; |
@@ -4670,7 +4672,6 @@ read_more: | |||
4670 | atomic_inc(&r10_bio->remaining); | 4672 | atomic_inc(&r10_bio->remaining); |
4671 | read_bio->bi_next = NULL; | 4673 | read_bio->bi_next = NULL; |
4672 | generic_make_request(read_bio); | 4674 | generic_make_request(read_bio); |
4673 | sector_nr += nr_sectors; | ||
4674 | sectors_done += nr_sectors; | 4675 | sectors_done += nr_sectors; |
4675 | if (sector_nr <= last) | 4676 | if (sector_nr <= last) |
4676 | goto read_more; | 4677 | goto read_more; |
diff --git a/drivers/md/raid5-log.h b/drivers/md/raid5-log.h index bfb811407061..43c714a8798c 100644 --- a/drivers/md/raid5-log.h +++ b/drivers/md/raid5-log.h | |||
@@ -45,6 +45,7 @@ extern void ppl_stripe_write_finished(struct stripe_head *sh); | |||
45 | extern int ppl_modify_log(struct r5conf *conf, struct md_rdev *rdev, bool add); | 45 | extern int ppl_modify_log(struct r5conf *conf, struct md_rdev *rdev, bool add); |
46 | extern void ppl_quiesce(struct r5conf *conf, int quiesce); | 46 | extern void ppl_quiesce(struct r5conf *conf, int quiesce); |
47 | extern int ppl_handle_flush_request(struct r5l_log *log, struct bio *bio); | 47 | extern int ppl_handle_flush_request(struct r5l_log *log, struct bio *bio); |
48 | extern struct md_sysfs_entry ppl_write_hint; | ||
48 | 49 | ||
49 | static inline bool raid5_has_log(struct r5conf *conf) | 50 | static inline bool raid5_has_log(struct r5conf *conf) |
50 | { | 51 | { |
diff --git a/drivers/md/raid5-ppl.c b/drivers/md/raid5-ppl.c index 0b096ddc9c1e..17e9e7d51097 100644 --- a/drivers/md/raid5-ppl.c +++ b/drivers/md/raid5-ppl.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/raid/md_p.h> | 20 | #include <linux/raid/md_p.h> |
21 | #include "md.h" | 21 | #include "md.h" |
22 | #include "raid5.h" | 22 | #include "raid5.h" |
23 | #include "raid5-log.h" | ||
23 | 24 | ||
24 | /* | 25 | /* |
25 | * PPL consists of a 4KB header (struct ppl_header) and at least 128KB for | 26 | * PPL consists of a 4KB header (struct ppl_header) and at least 128KB for |
@@ -115,6 +116,8 @@ struct ppl_conf { | |||
115 | /* stripes to retry if failed to allocate io_unit */ | 116 | /* stripes to retry if failed to allocate io_unit */ |
116 | struct list_head no_mem_stripes; | 117 | struct list_head no_mem_stripes; |
117 | spinlock_t no_mem_stripes_lock; | 118 | spinlock_t no_mem_stripes_lock; |
119 | |||
120 | unsigned short write_hint; | ||
118 | }; | 121 | }; |
119 | 122 | ||
120 | struct ppl_log { | 123 | struct ppl_log { |
@@ -474,6 +477,7 @@ static void ppl_submit_iounit(struct ppl_io_unit *io) | |||
474 | bio_set_dev(bio, log->rdev->bdev); | 477 | bio_set_dev(bio, log->rdev->bdev); |
475 | bio->bi_iter.bi_sector = log->next_io_sector; | 478 | bio->bi_iter.bi_sector = log->next_io_sector; |
476 | bio_add_page(bio, io->header_page, PAGE_SIZE, 0); | 479 | bio_add_page(bio, io->header_page, PAGE_SIZE, 0); |
480 | bio->bi_write_hint = ppl_conf->write_hint; | ||
477 | 481 | ||
478 | pr_debug("%s: log->current_io_sector: %llu\n", __func__, | 482 | pr_debug("%s: log->current_io_sector: %llu\n", __func__, |
479 | (unsigned long long)log->next_io_sector); | 483 | (unsigned long long)log->next_io_sector); |
@@ -503,6 +507,7 @@ static void ppl_submit_iounit(struct ppl_io_unit *io) | |||
503 | bio = bio_alloc_bioset(GFP_NOIO, BIO_MAX_PAGES, | 507 | bio = bio_alloc_bioset(GFP_NOIO, BIO_MAX_PAGES, |
504 | &ppl_conf->bs); | 508 | &ppl_conf->bs); |
505 | bio->bi_opf = prev->bi_opf; | 509 | bio->bi_opf = prev->bi_opf; |
510 | bio->bi_write_hint = prev->bi_write_hint; | ||
506 | bio_copy_dev(bio, prev); | 511 | bio_copy_dev(bio, prev); |
507 | bio->bi_iter.bi_sector = bio_end_sector(prev); | 512 | bio->bi_iter.bi_sector = bio_end_sector(prev); |
508 | bio_add_page(bio, sh->ppl_page, PAGE_SIZE, 0); | 513 | bio_add_page(bio, sh->ppl_page, PAGE_SIZE, 0); |
@@ -1407,6 +1412,7 @@ int ppl_init_log(struct r5conf *conf) | |||
1407 | atomic64_set(&ppl_conf->seq, 0); | 1412 | atomic64_set(&ppl_conf->seq, 0); |
1408 | INIT_LIST_HEAD(&ppl_conf->no_mem_stripes); | 1413 | INIT_LIST_HEAD(&ppl_conf->no_mem_stripes); |
1409 | spin_lock_init(&ppl_conf->no_mem_stripes_lock); | 1414 | spin_lock_init(&ppl_conf->no_mem_stripes_lock); |
1415 | ppl_conf->write_hint = RWF_WRITE_LIFE_NOT_SET; | ||
1410 | 1416 | ||
1411 | if (!mddev->external) { | 1417 | if (!mddev->external) { |
1412 | ppl_conf->signature = ~crc32c_le(~0, mddev->uuid, sizeof(mddev->uuid)); | 1418 | ppl_conf->signature = ~crc32c_le(~0, mddev->uuid, sizeof(mddev->uuid)); |
@@ -1501,3 +1507,60 @@ int ppl_modify_log(struct r5conf *conf, struct md_rdev *rdev, bool add) | |||
1501 | 1507 | ||
1502 | return ret; | 1508 | return ret; |
1503 | } | 1509 | } |
1510 | |||
1511 | static ssize_t | ||
1512 | ppl_write_hint_show(struct mddev *mddev, char *buf) | ||
1513 | { | ||
1514 | size_t ret = 0; | ||
1515 | struct r5conf *conf; | ||
1516 | struct ppl_conf *ppl_conf = NULL; | ||
1517 | |||
1518 | spin_lock(&mddev->lock); | ||
1519 | conf = mddev->private; | ||
1520 | if (conf && raid5_has_ppl(conf)) | ||
1521 | ppl_conf = conf->log_private; | ||
1522 | ret = sprintf(buf, "%d\n", ppl_conf ? ppl_conf->write_hint : 0); | ||
1523 | spin_unlock(&mddev->lock); | ||
1524 | |||
1525 | return ret; | ||
1526 | } | ||
1527 | |||
1528 | static ssize_t | ||
1529 | ppl_write_hint_store(struct mddev *mddev, const char *page, size_t len) | ||
1530 | { | ||
1531 | struct r5conf *conf; | ||
1532 | struct ppl_conf *ppl_conf; | ||
1533 | int err = 0; | ||
1534 | unsigned short new; | ||
1535 | |||
1536 | if (len >= PAGE_SIZE) | ||
1537 | return -EINVAL; | ||
1538 | if (kstrtou16(page, 10, &new)) | ||
1539 | return -EINVAL; | ||
1540 | |||
1541 | err = mddev_lock(mddev); | ||
1542 | if (err) | ||
1543 | return err; | ||
1544 | |||
1545 | conf = mddev->private; | ||
1546 | if (!conf) { | ||
1547 | err = -ENODEV; | ||
1548 | } else if (raid5_has_ppl(conf)) { | ||
1549 | ppl_conf = conf->log_private; | ||
1550 | if (!ppl_conf) | ||
1551 | err = -EINVAL; | ||
1552 | else | ||
1553 | ppl_conf->write_hint = new; | ||
1554 | } else { | ||
1555 | err = -EINVAL; | ||
1556 | } | ||
1557 | |||
1558 | mddev_unlock(mddev); | ||
1559 | |||
1560 | return err ?: len; | ||
1561 | } | ||
1562 | |||
1563 | struct md_sysfs_entry | ||
1564 | ppl_write_hint = __ATTR(ppl_write_hint, S_IRUGO | S_IWUSR, | ||
1565 | ppl_write_hint_show, | ||
1566 | ppl_write_hint_store); | ||
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 77ffd09be486..c033bfcb209e 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -6650,6 +6650,7 @@ static struct attribute *raid5_attrs[] = { | |||
6650 | &raid5_skip_copy.attr, | 6650 | &raid5_skip_copy.attr, |
6651 | &raid5_rmw_level.attr, | 6651 | &raid5_rmw_level.attr, |
6652 | &r5c_journal_mode.attr, | 6652 | &r5c_journal_mode.attr, |
6653 | &ppl_write_hint.attr, | ||
6653 | NULL, | 6654 | NULL, |
6654 | }; | 6655 | }; |
6655 | static struct attribute_group raid5_attrs_group = { | 6656 | static struct attribute_group raid5_attrs_group = { |
@@ -7393,6 +7394,8 @@ static int raid5_run(struct mddev *mddev) | |||
7393 | set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); | 7394 | set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); |
7394 | mddev->sync_thread = md_register_thread(md_do_sync, mddev, | 7395 | mddev->sync_thread = md_register_thread(md_do_sync, mddev, |
7395 | "reshape"); | 7396 | "reshape"); |
7397 | if (!mddev->sync_thread) | ||
7398 | goto abort; | ||
7396 | } | 7399 | } |
7397 | 7400 | ||
7398 | /* Ok, everything is just fine now */ | 7401 | /* Ok, everything is just fine now */ |
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 07bf2bff3a76..470601980794 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c | |||
@@ -179,8 +179,8 @@ static int nvme_delete_ctrl_sync(struct nvme_ctrl *ctrl) | |||
179 | int ret = 0; | 179 | int ret = 0; |
180 | 180 | ||
181 | /* | 181 | /* |
182 | * Keep a reference until the work is flushed since ->delete_ctrl | 182 | * Keep a reference until nvme_do_delete_ctrl() complete, |
183 | * can free the controller. | 183 | * since ->delete_ctrl can free the controller. |
184 | */ | 184 | */ |
185 | nvme_get_ctrl(ctrl); | 185 | nvme_get_ctrl(ctrl); |
186 | if (!nvme_change_ctrl_state(ctrl, NVME_CTRL_DELETING)) | 186 | if (!nvme_change_ctrl_state(ctrl, NVME_CTRL_DELETING)) |
@@ -1250,7 +1250,7 @@ static u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns, | |||
1250 | if (ns) { | 1250 | if (ns) { |
1251 | if (ctrl->effects) | 1251 | if (ctrl->effects) |
1252 | effects = le32_to_cpu(ctrl->effects->iocs[opcode]); | 1252 | effects = le32_to_cpu(ctrl->effects->iocs[opcode]); |
1253 | if (effects & ~NVME_CMD_EFFECTS_CSUPP) | 1253 | if (effects & ~(NVME_CMD_EFFECTS_CSUPP | NVME_CMD_EFFECTS_LBCC)) |
1254 | dev_warn(ctrl->device, | 1254 | dev_warn(ctrl->device, |
1255 | "IO command:%02x has unhandled effects:%08x\n", | 1255 | "IO command:%02x has unhandled effects:%08x\n", |
1256 | opcode, effects); | 1256 | opcode, effects); |
@@ -1495,10 +1495,10 @@ static void nvme_set_chunk_size(struct nvme_ns *ns) | |||
1495 | blk_queue_chunk_sectors(ns->queue, rounddown_pow_of_two(chunk_size)); | 1495 | blk_queue_chunk_sectors(ns->queue, rounddown_pow_of_two(chunk_size)); |
1496 | } | 1496 | } |
1497 | 1497 | ||
1498 | static void nvme_config_discard(struct nvme_ns *ns) | 1498 | static void nvme_config_discard(struct gendisk *disk, struct nvme_ns *ns) |
1499 | { | 1499 | { |
1500 | struct nvme_ctrl *ctrl = ns->ctrl; | 1500 | struct nvme_ctrl *ctrl = ns->ctrl; |
1501 | struct request_queue *queue = ns->queue; | 1501 | struct request_queue *queue = disk->queue; |
1502 | u32 size = queue_logical_block_size(queue); | 1502 | u32 size = queue_logical_block_size(queue); |
1503 | 1503 | ||
1504 | if (!(ctrl->oncs & NVME_CTRL_ONCS_DSM)) { | 1504 | if (!(ctrl->oncs & NVME_CTRL_ONCS_DSM)) { |
@@ -1526,12 +1526,13 @@ static void nvme_config_discard(struct nvme_ns *ns) | |||
1526 | blk_queue_max_write_zeroes_sectors(queue, UINT_MAX); | 1526 | blk_queue_max_write_zeroes_sectors(queue, UINT_MAX); |
1527 | } | 1527 | } |
1528 | 1528 | ||
1529 | static inline void nvme_config_write_zeroes(struct nvme_ns *ns) | 1529 | static void nvme_config_write_zeroes(struct gendisk *disk, struct nvme_ns *ns) |
1530 | { | 1530 | { |
1531 | u32 max_sectors; | 1531 | u32 max_sectors; |
1532 | unsigned short bs = 1 << ns->lba_shift; | 1532 | unsigned short bs = 1 << ns->lba_shift; |
1533 | 1533 | ||
1534 | if (!(ns->ctrl->oncs & NVME_CTRL_ONCS_WRITE_ZEROES)) | 1534 | if (!(ns->ctrl->oncs & NVME_CTRL_ONCS_WRITE_ZEROES) || |
1535 | (ns->ctrl->quirks & NVME_QUIRK_DISABLE_WRITE_ZEROES)) | ||
1535 | return; | 1536 | return; |
1536 | /* | 1537 | /* |
1537 | * Even though NVMe spec explicitly states that MDTS is not | 1538 | * Even though NVMe spec explicitly states that MDTS is not |
@@ -1548,13 +1549,7 @@ static inline void nvme_config_write_zeroes(struct nvme_ns *ns) | |||
1548 | else | 1549 | else |
1549 | max_sectors = ((u32)(ns->ctrl->max_hw_sectors + 1) * bs) >> 9; | 1550 | max_sectors = ((u32)(ns->ctrl->max_hw_sectors + 1) * bs) >> 9; |
1550 | 1551 | ||
1551 | blk_queue_max_write_zeroes_sectors(ns->queue, max_sectors); | 1552 | blk_queue_max_write_zeroes_sectors(disk->queue, max_sectors); |
1552 | } | ||
1553 | |||
1554 | static inline void nvme_ns_config_oncs(struct nvme_ns *ns) | ||
1555 | { | ||
1556 | nvme_config_discard(ns); | ||
1557 | nvme_config_write_zeroes(ns); | ||
1558 | } | 1553 | } |
1559 | 1554 | ||
1560 | static void nvme_report_ns_ids(struct nvme_ctrl *ctrl, unsigned int nsid, | 1555 | static void nvme_report_ns_ids(struct nvme_ctrl *ctrl, unsigned int nsid, |
@@ -1610,7 +1605,9 @@ static void nvme_update_disk_info(struct gendisk *disk, | |||
1610 | capacity = 0; | 1605 | capacity = 0; |
1611 | 1606 | ||
1612 | set_capacity(disk, capacity); | 1607 | set_capacity(disk, capacity); |
1613 | nvme_ns_config_oncs(ns); | 1608 | |
1609 | nvme_config_discard(disk, ns); | ||
1610 | nvme_config_write_zeroes(disk, ns); | ||
1614 | 1611 | ||
1615 | if (id->nsattr & (1 << 0)) | 1612 | if (id->nsattr & (1 << 0)) |
1616 | set_disk_ro(disk, true); | 1613 | set_disk_ro(disk, true); |
@@ -3304,6 +3301,7 @@ static int nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid) | |||
3304 | mutex_lock(&ctrl->subsys->lock); | 3301 | mutex_lock(&ctrl->subsys->lock); |
3305 | list_del_rcu(&ns->siblings); | 3302 | list_del_rcu(&ns->siblings); |
3306 | mutex_unlock(&ctrl->subsys->lock); | 3303 | mutex_unlock(&ctrl->subsys->lock); |
3304 | nvme_put_ns_head(ns->head); | ||
3307 | out_free_id: | 3305 | out_free_id: |
3308 | kfree(id); | 3306 | kfree(id); |
3309 | out_free_queue: | 3307 | out_free_queue: |
diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index b29b12498a1a..f3b9d91ba0df 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c | |||
@@ -2107,7 +2107,7 @@ nvme_fc_map_data(struct nvme_fc_ctrl *ctrl, struct request *rq, | |||
2107 | 2107 | ||
2108 | freq->sg_cnt = 0; | 2108 | freq->sg_cnt = 0; |
2109 | 2109 | ||
2110 | if (!blk_rq_payload_bytes(rq)) | 2110 | if (!blk_rq_nr_phys_segments(rq)) |
2111 | return 0; | 2111 | return 0; |
2112 | 2112 | ||
2113 | freq->sg_table.sgl = freq->first_sgl; | 2113 | freq->sg_table.sgl = freq->first_sgl; |
@@ -2304,12 +2304,23 @@ nvme_fc_queue_rq(struct blk_mq_hw_ctx *hctx, | |||
2304 | if (ret) | 2304 | if (ret) |
2305 | return ret; | 2305 | return ret; |
2306 | 2306 | ||
2307 | data_len = blk_rq_payload_bytes(rq); | 2307 | /* |
2308 | if (data_len) | 2308 | * nvme core doesn't quite treat the rq opaquely. Commands such |
2309 | * as WRITE ZEROES will return a non-zero rq payload_bytes yet | ||
2310 | * there is no actual payload to be transferred. | ||
2311 | * To get it right, key data transmission on there being 1 or | ||
2312 | * more physical segments in the sg list. If there is no | ||
2313 | * physical segments, there is no payload. | ||
2314 | */ | ||
2315 | if (blk_rq_nr_phys_segments(rq)) { | ||
2316 | data_len = blk_rq_payload_bytes(rq); | ||
2309 | io_dir = ((rq_data_dir(rq) == WRITE) ? | 2317 | io_dir = ((rq_data_dir(rq) == WRITE) ? |
2310 | NVMEFC_FCP_WRITE : NVMEFC_FCP_READ); | 2318 | NVMEFC_FCP_WRITE : NVMEFC_FCP_READ); |
2311 | else | 2319 | } else { |
2320 | data_len = 0; | ||
2312 | io_dir = NVMEFC_FCP_NODATA; | 2321 | io_dir = NVMEFC_FCP_NODATA; |
2322 | } | ||
2323 | |||
2313 | 2324 | ||
2314 | return nvme_fc_start_fcp_op(ctrl, queue, op, data_len, io_dir); | 2325 | return nvme_fc_start_fcp_op(ctrl, queue, op, data_len, io_dir); |
2315 | } | 2326 | } |
@@ -2464,6 +2475,7 @@ static int | |||
2464 | nvme_fc_recreate_io_queues(struct nvme_fc_ctrl *ctrl) | 2475 | nvme_fc_recreate_io_queues(struct nvme_fc_ctrl *ctrl) |
2465 | { | 2476 | { |
2466 | struct nvmf_ctrl_options *opts = ctrl->ctrl.opts; | 2477 | struct nvmf_ctrl_options *opts = ctrl->ctrl.opts; |
2478 | u32 prior_ioq_cnt = ctrl->ctrl.queue_count - 1; | ||
2467 | unsigned int nr_io_queues; | 2479 | unsigned int nr_io_queues; |
2468 | int ret; | 2480 | int ret; |
2469 | 2481 | ||
@@ -2476,6 +2488,13 @@ nvme_fc_recreate_io_queues(struct nvme_fc_ctrl *ctrl) | |||
2476 | return ret; | 2488 | return ret; |
2477 | } | 2489 | } |
2478 | 2490 | ||
2491 | if (!nr_io_queues && prior_ioq_cnt) { | ||
2492 | dev_info(ctrl->ctrl.device, | ||
2493 | "Fail Reconnect: At least 1 io queue " | ||
2494 | "required (was %d)\n", prior_ioq_cnt); | ||
2495 | return -ENOSPC; | ||
2496 | } | ||
2497 | |||
2479 | ctrl->ctrl.queue_count = nr_io_queues + 1; | 2498 | ctrl->ctrl.queue_count = nr_io_queues + 1; |
2480 | /* check for io queues existing */ | 2499 | /* check for io queues existing */ |
2481 | if (ctrl->ctrl.queue_count == 1) | 2500 | if (ctrl->ctrl.queue_count == 1) |
@@ -2489,6 +2508,10 @@ nvme_fc_recreate_io_queues(struct nvme_fc_ctrl *ctrl) | |||
2489 | if (ret) | 2508 | if (ret) |
2490 | goto out_delete_hw_queues; | 2509 | goto out_delete_hw_queues; |
2491 | 2510 | ||
2511 | if (prior_ioq_cnt != nr_io_queues) | ||
2512 | dev_info(ctrl->ctrl.device, | ||
2513 | "reconnect: revising io queue count from %d to %d\n", | ||
2514 | prior_ioq_cnt, nr_io_queues); | ||
2492 | blk_mq_update_nr_hw_queues(&ctrl->tag_set, nr_io_queues); | 2515 | blk_mq_update_nr_hw_queues(&ctrl->tag_set, nr_io_queues); |
2493 | 2516 | ||
2494 | return 0; | 2517 | return 0; |
@@ -3006,7 +3029,10 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts, | |||
3006 | 3029 | ||
3007 | ctrl->ctrl.opts = opts; | 3030 | ctrl->ctrl.opts = opts; |
3008 | ctrl->ctrl.nr_reconnects = 0; | 3031 | ctrl->ctrl.nr_reconnects = 0; |
3009 | ctrl->ctrl.numa_node = dev_to_node(lport->dev); | 3032 | if (lport->dev) |
3033 | ctrl->ctrl.numa_node = dev_to_node(lport->dev); | ||
3034 | else | ||
3035 | ctrl->ctrl.numa_node = NUMA_NO_NODE; | ||
3010 | INIT_LIST_HEAD(&ctrl->ctrl_list); | 3036 | INIT_LIST_HEAD(&ctrl->ctrl_list); |
3011 | ctrl->lport = lport; | 3037 | ctrl->lport = lport; |
3012 | ctrl->rport = rport; | 3038 | ctrl->rport = rport; |
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index b91f1838bbd5..527d64545023 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h | |||
@@ -87,6 +87,11 @@ enum nvme_quirks { | |||
87 | * Ignore device provided subnqn. | 87 | * Ignore device provided subnqn. |
88 | */ | 88 | */ |
89 | NVME_QUIRK_IGNORE_DEV_SUBNQN = (1 << 8), | 89 | NVME_QUIRK_IGNORE_DEV_SUBNQN = (1 << 8), |
90 | |||
91 | /* | ||
92 | * Broken Write Zeroes. | ||
93 | */ | ||
94 | NVME_QUIRK_DISABLE_WRITE_ZEROES = (1 << 9), | ||
90 | }; | 95 | }; |
91 | 96 | ||
92 | /* | 97 | /* |
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 92bad1c810ac..a90cf5d63aac 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c | |||
@@ -2937,7 +2937,8 @@ static const struct pci_device_id nvme_id_table[] = { | |||
2937 | { PCI_VDEVICE(INTEL, 0xf1a6), /* Intel 760p/Pro 7600p */ | 2937 | { PCI_VDEVICE(INTEL, 0xf1a6), /* Intel 760p/Pro 7600p */ |
2938 | .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, }, | 2938 | .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, }, |
2939 | { PCI_VDEVICE(INTEL, 0x5845), /* Qemu emulated controller */ | 2939 | { PCI_VDEVICE(INTEL, 0x5845), /* Qemu emulated controller */ |
2940 | .driver_data = NVME_QUIRK_IDENTIFY_CNS, }, | 2940 | .driver_data = NVME_QUIRK_IDENTIFY_CNS | |
2941 | NVME_QUIRK_DISABLE_WRITE_ZEROES, }, | ||
2941 | { PCI_DEVICE(0x1bb1, 0x0100), /* Seagate Nytro Flash Storage */ | 2942 | { PCI_DEVICE(0x1bb1, 0x0100), /* Seagate Nytro Flash Storage */ |
2942 | .driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, }, | 2943 | .driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, }, |
2943 | { PCI_DEVICE(0x1c58, 0x0003), /* HGST adapter */ | 2944 | { PCI_DEVICE(0x1c58, 0x0003), /* HGST adapter */ |
diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index 208ee518af65..e7e08889865e 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c | |||
@@ -463,6 +463,15 @@ static int nvme_tcp_handle_c2h_data(struct nvme_tcp_queue *queue, | |||
463 | 463 | ||
464 | queue->data_remaining = le32_to_cpu(pdu->data_length); | 464 | queue->data_remaining = le32_to_cpu(pdu->data_length); |
465 | 465 | ||
466 | if (pdu->hdr.flags & NVME_TCP_F_DATA_SUCCESS && | ||
467 | unlikely(!(pdu->hdr.flags & NVME_TCP_F_DATA_LAST))) { | ||
468 | dev_err(queue->ctrl->ctrl.device, | ||
469 | "queue %d tag %#x SUCCESS set but not last PDU\n", | ||
470 | nvme_tcp_queue_id(queue), rq->tag); | ||
471 | nvme_tcp_error_recovery(&queue->ctrl->ctrl); | ||
472 | return -EPROTO; | ||
473 | } | ||
474 | |||
466 | return 0; | 475 | return 0; |
467 | 476 | ||
468 | } | 477 | } |
@@ -618,6 +627,14 @@ static int nvme_tcp_recv_pdu(struct nvme_tcp_queue *queue, struct sk_buff *skb, | |||
618 | return ret; | 627 | return ret; |
619 | } | 628 | } |
620 | 629 | ||
630 | static inline void nvme_tcp_end_request(struct request *rq, __le16 status) | ||
631 | { | ||
632 | union nvme_result res = {}; | ||
633 | |||
634 | nvme_end_request(rq, cpu_to_le16(status << 1), res); | ||
635 | } | ||
636 | |||
637 | |||
621 | static int nvme_tcp_recv_data(struct nvme_tcp_queue *queue, struct sk_buff *skb, | 638 | static int nvme_tcp_recv_data(struct nvme_tcp_queue *queue, struct sk_buff *skb, |
622 | unsigned int *offset, size_t *len) | 639 | unsigned int *offset, size_t *len) |
623 | { | 640 | { |
@@ -685,6 +702,8 @@ static int nvme_tcp_recv_data(struct nvme_tcp_queue *queue, struct sk_buff *skb, | |||
685 | nvme_tcp_ddgst_final(queue->rcv_hash, &queue->exp_ddgst); | 702 | nvme_tcp_ddgst_final(queue->rcv_hash, &queue->exp_ddgst); |
686 | queue->ddgst_remaining = NVME_TCP_DIGEST_LENGTH; | 703 | queue->ddgst_remaining = NVME_TCP_DIGEST_LENGTH; |
687 | } else { | 704 | } else { |
705 | if (pdu->hdr.flags & NVME_TCP_F_DATA_SUCCESS) | ||
706 | nvme_tcp_end_request(rq, NVME_SC_SUCCESS); | ||
688 | nvme_tcp_init_recv_ctx(queue); | 707 | nvme_tcp_init_recv_ctx(queue); |
689 | } | 708 | } |
690 | } | 709 | } |
@@ -695,6 +714,7 @@ static int nvme_tcp_recv_data(struct nvme_tcp_queue *queue, struct sk_buff *skb, | |||
695 | static int nvme_tcp_recv_ddgst(struct nvme_tcp_queue *queue, | 714 | static int nvme_tcp_recv_ddgst(struct nvme_tcp_queue *queue, |
696 | struct sk_buff *skb, unsigned int *offset, size_t *len) | 715 | struct sk_buff *skb, unsigned int *offset, size_t *len) |
697 | { | 716 | { |
717 | struct nvme_tcp_data_pdu *pdu = (void *)queue->pdu; | ||
698 | char *ddgst = (char *)&queue->recv_ddgst; | 718 | char *ddgst = (char *)&queue->recv_ddgst; |
699 | size_t recv_len = min_t(size_t, *len, queue->ddgst_remaining); | 719 | size_t recv_len = min_t(size_t, *len, queue->ddgst_remaining); |
700 | off_t off = NVME_TCP_DIGEST_LENGTH - queue->ddgst_remaining; | 720 | off_t off = NVME_TCP_DIGEST_LENGTH - queue->ddgst_remaining; |
@@ -718,6 +738,13 @@ static int nvme_tcp_recv_ddgst(struct nvme_tcp_queue *queue, | |||
718 | return -EIO; | 738 | return -EIO; |
719 | } | 739 | } |
720 | 740 | ||
741 | if (pdu->hdr.flags & NVME_TCP_F_DATA_SUCCESS) { | ||
742 | struct request *rq = blk_mq_tag_to_rq(nvme_tcp_tagset(queue), | ||
743 | pdu->command_id); | ||
744 | |||
745 | nvme_tcp_end_request(rq, NVME_SC_SUCCESS); | ||
746 | } | ||
747 | |||
721 | nvme_tcp_init_recv_ctx(queue); | 748 | nvme_tcp_init_recv_ctx(queue); |
722 | return 0; | 749 | return 0; |
723 | } | 750 | } |
@@ -815,10 +842,7 @@ static inline void nvme_tcp_done_send_req(struct nvme_tcp_queue *queue) | |||
815 | 842 | ||
816 | static void nvme_tcp_fail_request(struct nvme_tcp_request *req) | 843 | static void nvme_tcp_fail_request(struct nvme_tcp_request *req) |
817 | { | 844 | { |
818 | union nvme_result res = {}; | 845 | nvme_tcp_end_request(blk_mq_rq_from_pdu(req), NVME_SC_DATA_XFER_ERROR); |
819 | |||
820 | nvme_end_request(blk_mq_rq_from_pdu(req), | ||
821 | cpu_to_le16(NVME_SC_DATA_XFER_ERROR), res); | ||
822 | } | 846 | } |
823 | 847 | ||
824 | static int nvme_tcp_try_send_data(struct nvme_tcp_request *req) | 848 | static int nvme_tcp_try_send_data(struct nvme_tcp_request *req) |
diff --git a/drivers/nvme/host/trace.c b/drivers/nvme/host/trace.c index 58456de78bb2..5f24ea7a28eb 100644 --- a/drivers/nvme/host/trace.c +++ b/drivers/nvme/host/trace.c | |||
@@ -50,7 +50,19 @@ static const char *nvme_trace_admin_identify(struct trace_seq *p, u8 *cdw10) | |||
50 | return ret; | 50 | return ret; |
51 | } | 51 | } |
52 | 52 | ||
53 | static const char *nvme_trace_admin_get_features(struct trace_seq *p, | ||
54 | u8 *cdw10) | ||
55 | { | ||
56 | const char *ret = trace_seq_buffer_ptr(p); | ||
57 | u8 fid = cdw10[0]; | ||
58 | u8 sel = cdw10[1] & 0x7; | ||
59 | u32 cdw11 = get_unaligned_le32(cdw10 + 4); | ||
60 | |||
61 | trace_seq_printf(p, "fid=0x%x sel=0x%x cdw11=0x%x", fid, sel, cdw11); | ||
62 | trace_seq_putc(p, 0); | ||
53 | 63 | ||
64 | return ret; | ||
65 | } | ||
54 | 66 | ||
55 | static const char *nvme_trace_read_write(struct trace_seq *p, u8 *cdw10) | 67 | static const char *nvme_trace_read_write(struct trace_seq *p, u8 *cdw10) |
56 | { | 68 | { |
@@ -101,6 +113,8 @@ const char *nvme_trace_parse_admin_cmd(struct trace_seq *p, | |||
101 | return nvme_trace_create_cq(p, cdw10); | 113 | return nvme_trace_create_cq(p, cdw10); |
102 | case nvme_admin_identify: | 114 | case nvme_admin_identify: |
103 | return nvme_trace_admin_identify(p, cdw10); | 115 | return nvme_trace_admin_identify(p, cdw10); |
116 | case nvme_admin_get_features: | ||
117 | return nvme_trace_admin_get_features(p, cdw10); | ||
104 | default: | 118 | default: |
105 | return nvme_trace_common(p, cdw10); | 119 | return nvme_trace_common(p, cdw10); |
106 | } | 120 | } |
diff --git a/drivers/nvme/host/trace.h b/drivers/nvme/host/trace.h index 244d7c177e5a..97d3c77365b8 100644 --- a/drivers/nvme/host/trace.h +++ b/drivers/nvme/host/trace.h | |||
@@ -108,7 +108,7 @@ TRACE_EVENT(nvme_setup_cmd, | |||
108 | __entry->metadata = le64_to_cpu(cmd->common.metadata); | 108 | __entry->metadata = le64_to_cpu(cmd->common.metadata); |
109 | __assign_disk_name(__entry->disk, req->rq_disk); | 109 | __assign_disk_name(__entry->disk, req->rq_disk); |
110 | memcpy(__entry->cdw10, &cmd->common.cdw10, | 110 | memcpy(__entry->cdw10, &cmd->common.cdw10, |
111 | 6 * sizeof(__entry->cdw10)); | 111 | sizeof(__entry->cdw10)); |
112 | ), | 112 | ), |
113 | TP_printk("nvme%d: %sqid=%d, cmdid=%u, nsid=%u, flags=0x%x, meta=0x%llx, cmd=(%s %s)", | 113 | TP_printk("nvme%d: %sqid=%d, cmdid=%u, nsid=%u, flags=0x%x, meta=0x%llx, cmd=(%s %s)", |
114 | __entry->ctrl_id, __print_disk_name(__entry->disk), | 114 | __entry->ctrl_id, __print_disk_name(__entry->disk), |
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index d44ede147263..2d73b66e3686 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c | |||
@@ -1163,6 +1163,15 @@ static void nvmet_release_p2p_ns_map(struct nvmet_ctrl *ctrl) | |||
1163 | put_device(ctrl->p2p_client); | 1163 | put_device(ctrl->p2p_client); |
1164 | } | 1164 | } |
1165 | 1165 | ||
1166 | static void nvmet_fatal_error_handler(struct work_struct *work) | ||
1167 | { | ||
1168 | struct nvmet_ctrl *ctrl = | ||
1169 | container_of(work, struct nvmet_ctrl, fatal_err_work); | ||
1170 | |||
1171 | pr_err("ctrl %d fatal error occurred!\n", ctrl->cntlid); | ||
1172 | ctrl->ops->delete_ctrl(ctrl); | ||
1173 | } | ||
1174 | |||
1166 | u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn, | 1175 | u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn, |
1167 | struct nvmet_req *req, u32 kato, struct nvmet_ctrl **ctrlp) | 1176 | struct nvmet_req *req, u32 kato, struct nvmet_ctrl **ctrlp) |
1168 | { | 1177 | { |
@@ -1205,6 +1214,7 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn, | |||
1205 | INIT_WORK(&ctrl->async_event_work, nvmet_async_event_work); | 1214 | INIT_WORK(&ctrl->async_event_work, nvmet_async_event_work); |
1206 | INIT_LIST_HEAD(&ctrl->async_events); | 1215 | INIT_LIST_HEAD(&ctrl->async_events); |
1207 | INIT_RADIX_TREE(&ctrl->p2p_ns_map, GFP_KERNEL); | 1216 | INIT_RADIX_TREE(&ctrl->p2p_ns_map, GFP_KERNEL); |
1217 | INIT_WORK(&ctrl->fatal_err_work, nvmet_fatal_error_handler); | ||
1208 | 1218 | ||
1209 | memcpy(ctrl->subsysnqn, subsysnqn, NVMF_NQN_SIZE); | 1219 | memcpy(ctrl->subsysnqn, subsysnqn, NVMF_NQN_SIZE); |
1210 | memcpy(ctrl->hostnqn, hostnqn, NVMF_NQN_SIZE); | 1220 | memcpy(ctrl->hostnqn, hostnqn, NVMF_NQN_SIZE); |
@@ -1308,21 +1318,11 @@ void nvmet_ctrl_put(struct nvmet_ctrl *ctrl) | |||
1308 | kref_put(&ctrl->ref, nvmet_ctrl_free); | 1318 | kref_put(&ctrl->ref, nvmet_ctrl_free); |
1309 | } | 1319 | } |
1310 | 1320 | ||
1311 | static void nvmet_fatal_error_handler(struct work_struct *work) | ||
1312 | { | ||
1313 | struct nvmet_ctrl *ctrl = | ||
1314 | container_of(work, struct nvmet_ctrl, fatal_err_work); | ||
1315 | |||
1316 | pr_err("ctrl %d fatal error occurred!\n", ctrl->cntlid); | ||
1317 | ctrl->ops->delete_ctrl(ctrl); | ||
1318 | } | ||
1319 | |||
1320 | void nvmet_ctrl_fatal_error(struct nvmet_ctrl *ctrl) | 1321 | void nvmet_ctrl_fatal_error(struct nvmet_ctrl *ctrl) |
1321 | { | 1322 | { |
1322 | mutex_lock(&ctrl->lock); | 1323 | mutex_lock(&ctrl->lock); |
1323 | if (!(ctrl->csts & NVME_CSTS_CFS)) { | 1324 | if (!(ctrl->csts & NVME_CSTS_CFS)) { |
1324 | ctrl->csts |= NVME_CSTS_CFS; | 1325 | ctrl->csts |= NVME_CSTS_CFS; |
1325 | INIT_WORK(&ctrl->fatal_err_work, nvmet_fatal_error_handler); | ||
1326 | schedule_work(&ctrl->fatal_err_work); | 1326 | schedule_work(&ctrl->fatal_err_work); |
1327 | } | 1327 | } |
1328 | mutex_unlock(&ctrl->lock); | 1328 | mutex_unlock(&ctrl->lock); |
diff --git a/drivers/nvme/target/fc.c b/drivers/nvme/target/fc.c index 1e9654f04c60..98b7b1f4ee96 100644 --- a/drivers/nvme/target/fc.c +++ b/drivers/nvme/target/fc.c | |||
@@ -1143,10 +1143,8 @@ __nvmet_fc_free_assocs(struct nvmet_fc_tgtport *tgtport) | |||
1143 | &tgtport->assoc_list, a_list) { | 1143 | &tgtport->assoc_list, a_list) { |
1144 | if (!nvmet_fc_tgt_a_get(assoc)) | 1144 | if (!nvmet_fc_tgt_a_get(assoc)) |
1145 | continue; | 1145 | continue; |
1146 | spin_unlock_irqrestore(&tgtport->lock, flags); | 1146 | if (!schedule_work(&assoc->del_work)) |
1147 | nvmet_fc_delete_target_assoc(assoc); | 1147 | nvmet_fc_tgt_a_put(assoc); |
1148 | nvmet_fc_tgt_a_put(assoc); | ||
1149 | spin_lock_irqsave(&tgtport->lock, flags); | ||
1150 | } | 1148 | } |
1151 | spin_unlock_irqrestore(&tgtport->lock, flags); | 1149 | spin_unlock_irqrestore(&tgtport->lock, flags); |
1152 | } | 1150 | } |
@@ -1185,7 +1183,8 @@ nvmet_fc_delete_ctrl(struct nvmet_ctrl *ctrl) | |||
1185 | nvmet_fc_tgtport_put(tgtport); | 1183 | nvmet_fc_tgtport_put(tgtport); |
1186 | 1184 | ||
1187 | if (found_ctrl) { | 1185 | if (found_ctrl) { |
1188 | schedule_work(&assoc->del_work); | 1186 | if (!schedule_work(&assoc->del_work)) |
1187 | nvmet_fc_tgt_a_put(assoc); | ||
1189 | return; | 1188 | return; |
1190 | } | 1189 | } |
1191 | 1190 | ||
@@ -1503,10 +1502,8 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport, | |||
1503 | (struct fcnvme_ls_disconnect_rqst *)iod->rqstbuf; | 1502 | (struct fcnvme_ls_disconnect_rqst *)iod->rqstbuf; |
1504 | struct fcnvme_ls_disconnect_acc *acc = | 1503 | struct fcnvme_ls_disconnect_acc *acc = |
1505 | (struct fcnvme_ls_disconnect_acc *)iod->rspbuf; | 1504 | (struct fcnvme_ls_disconnect_acc *)iod->rspbuf; |
1506 | struct nvmet_fc_tgt_queue *queue = NULL; | ||
1507 | struct nvmet_fc_tgt_assoc *assoc; | 1505 | struct nvmet_fc_tgt_assoc *assoc; |
1508 | int ret = 0; | 1506 | int ret = 0; |
1509 | bool del_assoc = false; | ||
1510 | 1507 | ||
1511 | memset(acc, 0, sizeof(*acc)); | 1508 | memset(acc, 0, sizeof(*acc)); |
1512 | 1509 | ||
@@ -1537,18 +1534,7 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport, | |||
1537 | assoc = nvmet_fc_find_target_assoc(tgtport, | 1534 | assoc = nvmet_fc_find_target_assoc(tgtport, |
1538 | be64_to_cpu(rqst->associd.association_id)); | 1535 | be64_to_cpu(rqst->associd.association_id)); |
1539 | iod->assoc = assoc; | 1536 | iod->assoc = assoc; |
1540 | if (assoc) { | 1537 | if (!assoc) |
1541 | if (rqst->discon_cmd.scope == | ||
1542 | FCNVME_DISCONN_CONNECTION) { | ||
1543 | queue = nvmet_fc_find_target_queue(tgtport, | ||
1544 | be64_to_cpu( | ||
1545 | rqst->discon_cmd.id)); | ||
1546 | if (!queue) { | ||
1547 | nvmet_fc_tgt_a_put(assoc); | ||
1548 | ret = VERR_NO_CONN; | ||
1549 | } | ||
1550 | } | ||
1551 | } else | ||
1552 | ret = VERR_NO_ASSOC; | 1538 | ret = VERR_NO_ASSOC; |
1553 | } | 1539 | } |
1554 | 1540 | ||
@@ -1576,26 +1562,10 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport, | |||
1576 | sizeof(struct fcnvme_ls_disconnect_acc)), | 1562 | sizeof(struct fcnvme_ls_disconnect_acc)), |
1577 | FCNVME_LS_DISCONNECT); | 1563 | FCNVME_LS_DISCONNECT); |
1578 | 1564 | ||
1579 | |||
1580 | /* are we to delete a Connection ID (queue) */ | ||
1581 | if (queue) { | ||
1582 | int qid = queue->qid; | ||
1583 | |||
1584 | nvmet_fc_delete_target_queue(queue); | ||
1585 | |||
1586 | /* release the get taken by find_target_queue */ | ||
1587 | nvmet_fc_tgt_q_put(queue); | ||
1588 | |||
1589 | /* tear association down if io queue terminated */ | ||
1590 | if (!qid) | ||
1591 | del_assoc = true; | ||
1592 | } | ||
1593 | |||
1594 | /* release get taken in nvmet_fc_find_target_assoc */ | 1565 | /* release get taken in nvmet_fc_find_target_assoc */ |
1595 | nvmet_fc_tgt_a_put(iod->assoc); | 1566 | nvmet_fc_tgt_a_put(iod->assoc); |
1596 | 1567 | ||
1597 | if (del_assoc) | 1568 | nvmet_fc_delete_target_assoc(iod->assoc); |
1598 | nvmet_fc_delete_target_assoc(iod->assoc); | ||
1599 | } | 1569 | } |
1600 | 1570 | ||
1601 | 1571 | ||
diff --git a/drivers/nvme/target/io-cmd-bdev.c b/drivers/nvme/target/io-cmd-bdev.c index 71dfedbadc26..a065dbfc43b1 100644 --- a/drivers/nvme/target/io-cmd-bdev.c +++ b/drivers/nvme/target/io-cmd-bdev.c | |||
@@ -194,11 +194,11 @@ static u16 nvmet_bdev_discard_range(struct nvmet_req *req, | |||
194 | le64_to_cpu(range->slba) << (ns->blksize_shift - 9), | 194 | le64_to_cpu(range->slba) << (ns->blksize_shift - 9), |
195 | le32_to_cpu(range->nlb) << (ns->blksize_shift - 9), | 195 | le32_to_cpu(range->nlb) << (ns->blksize_shift - 9), |
196 | GFP_KERNEL, 0, bio); | 196 | GFP_KERNEL, 0, bio); |
197 | 197 | if (ret && ret != -EOPNOTSUPP) { | |
198 | if (ret) | ||
199 | req->error_slba = le64_to_cpu(range->slba); | 198 | req->error_slba = le64_to_cpu(range->slba); |
200 | 199 | return blk_to_nvme_status(req, errno_to_blk_status(ret)); | |
201 | return blk_to_nvme_status(req, errno_to_blk_status(ret)); | 200 | } |
201 | return NVME_SC_SUCCESS; | ||
202 | } | 202 | } |
203 | 203 | ||
204 | static void nvmet_bdev_execute_discard(struct nvmet_req *req) | 204 | static void nvmet_bdev_execute_discard(struct nvmet_req *req) |
diff --git a/drivers/nvme/target/io-cmd-file.c b/drivers/nvme/target/io-cmd-file.c index 517522305e5c..3e43212d3c1c 100644 --- a/drivers/nvme/target/io-cmd-file.c +++ b/drivers/nvme/target/io-cmd-file.c | |||
@@ -297,7 +297,7 @@ static void nvmet_file_execute_discard(struct nvmet_req *req) | |||
297 | } | 297 | } |
298 | 298 | ||
299 | ret = vfs_fallocate(req->ns->file, mode, offset, len); | 299 | ret = vfs_fallocate(req->ns->file, mode, offset, len); |
300 | if (ret) { | 300 | if (ret && ret != -EOPNOTSUPP) { |
301 | req->error_slba = le64_to_cpu(range.slba); | 301 | req->error_slba = le64_to_cpu(range.slba); |
302 | status = errno_to_nvme_status(req, ret); | 302 | status = errno_to_nvme_status(req, ret); |
303 | break; | 303 | break; |
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index fac0ddf8a8e2..e1c6d79fb4cc 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c | |||
@@ -723,6 +723,7 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg) | |||
723 | #endif | 723 | #endif |
724 | case BLKTRACESTART: | 724 | case BLKTRACESTART: |
725 | start = 1; | 725 | start = 1; |
726 | /* fall through */ | ||
726 | case BLKTRACESTOP: | 727 | case BLKTRACESTOP: |
727 | ret = __blk_trace_startstop(q, start); | 728 | ret = __blk_trace_startstop(q, start); |
728 | break; | 729 | break; |