Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'block-5.13-2021-05-14' of git://git.kernel.dk/linux-block

Pull block fixes from Jens Axboe:

- Fix for shared tag set exit (Bart)

- Correct ioctl range for zoned ioctls (Damien)

- Removed dead/unused function (Lin)

- Fix perf regression for shared tags (Ming)

- Fix out-of-bounds issue with kyber and preemption (Omar)

- BFQ merge fix (Paolo)

- Two error handling fixes for nbd (Sun)

- Fix weight update in blk-iocost (Tejun)

- NVMe pull request (Christoph):
- correct the check for using the inline bio in nvmet (Chaitanya
Kulkarni)
- demote unsupported command warnings (Chaitanya Kulkarni)
- fix corruption due to double initializing ANA state (me, Hou Pu)
- reset ns->file when open fails (Daniel Wagner)
- fix a NULL deref when SEND is completed with error in nvmet-rdma
(Michal Kalderon)

- Fix kernel-doc warning (Bart)

* tag 'block-5.13-2021-05-14' of git://git.kernel.dk/linux-block:
block/partitions/efi.c: Fix the efi_partition() kernel-doc header
blk-mq: Swap two calls in blk_mq_exit_queue()
blk-mq: plug request for shared sbitmap
nvmet: use new ana_log_size instead the old one
nvmet: seset ns->file when open fails
nbd: share nbd_put and return by goto put_nbd
nbd: Fix NULL pointer in flush_workqueue
blkdev.h: remove unused codes blk_account_rq
block, bfq: avoid circular stable merges
blk-iocost: fix weight updates of inner active iocgs
nvmet: demote fabrics cmd parse err msg to debug
nvmet: use helper to remove the duplicate code
nvmet: demote discovery cmd parse err msg to debug
nvmet-rdma: Fix NULL deref when SEND is completed with error
nvmet: fix inline bio check for passthru
nvmet: fix inline bio check for bdev-ns
nvme-multipath: fix double initialization of ANA state
kyber: fix out of bounds access when preempted
block: uapi: fix comment about block device ioctl

+124 -75
+30 -4
block/bfq-iosched.c
··· 372 372 return bic->bfqq[is_sync]; 373 373 } 374 374 375 + static void bfq_put_stable_ref(struct bfq_queue *bfqq); 376 + 375 377 void bic_set_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq, bool is_sync) 376 378 { 379 + /* 380 + * If bfqq != NULL, then a non-stable queue merge between 381 + * bic->bfqq and bfqq is happening here. This causes troubles 382 + * in the following case: bic->bfqq has also been scheduled 383 + * for a possible stable merge with bic->stable_merge_bfqq, 384 + * and bic->stable_merge_bfqq == bfqq happens to 385 + * hold. Troubles occur because bfqq may then undergo a split, 386 + * thereby becoming eligible for a stable merge. Yet, if 387 + * bic->stable_merge_bfqq points exactly to bfqq, then bfqq 388 + * would be stably merged with itself. To avoid this anomaly, 389 + * we cancel the stable merge if 390 + * bic->stable_merge_bfqq == bfqq. 391 + */ 377 392 bic->bfqq[is_sync] = bfqq; 393 + 394 + if (bfqq && bic->stable_merge_bfqq == bfqq) { 395 + /* 396 + * Actually, these same instructions are executed also 397 + * in bfq_setup_cooperator, in case of abort or actual 398 + * execution of a stable merge. We could avoid 399 + * repeating these instructions there too, but if we 400 + * did so, we would nest even more complexity in this 401 + * function. 402 + */ 403 + bfq_put_stable_ref(bic->stable_merge_bfqq); 404 + 405 + bic->stable_merge_bfqq = NULL; 406 + } 378 407 } 379 408 380 409 struct bfq_data *bic_to_bfqd(struct bfq_io_cq *bic) ··· 2292 2263 2293 2264 } 2294 2265 2295 - static bool bfq_bio_merge(struct blk_mq_hw_ctx *hctx, struct bio *bio, 2266 + static bool bfq_bio_merge(struct request_queue *q, struct bio *bio, 2296 2267 unsigned int nr_segs) 2297 2268 { 2298 - struct request_queue *q = hctx->queue; 2299 2269 struct bfq_data *bfqd = q->elevator->elevator_data; 2300 2270 struct request *free = NULL; 2301 2271 /* ··· 2658 2630 2659 2631 static bool idling_boosts_thr_without_issues(struct bfq_data *bfqd, 2660 2632 struct bfq_queue *bfqq); 2661 - 2662 - static void bfq_put_stable_ref(struct bfq_queue *bfqq); 2663 2633 2664 2634 /* 2665 2635 * Attempt to schedule a merge of bfqq with the currently in-service
+12 -2
block/blk-iocost.c
··· 1069 1069 1070 1070 lockdep_assert_held(&ioc->lock); 1071 1071 1072 - inuse = clamp_t(u32, inuse, 1, active); 1072 + /* 1073 + * For an active leaf node, its inuse shouldn't be zero or exceed 1074 + * @active. An active internal node's inuse is solely determined by the 1075 + * inuse to active ratio of its children regardless of @inuse. 1076 + */ 1077 + if (list_empty(&iocg->active_list) && iocg->child_active_sum) { 1078 + inuse = DIV64_U64_ROUND_UP(active * iocg->child_inuse_sum, 1079 + iocg->child_active_sum); 1080 + } else { 1081 + inuse = clamp_t(u32, inuse, 1, active); 1082 + } 1073 1083 1074 1084 iocg->last_inuse = iocg->inuse; 1075 1085 if (save) ··· 1096 1086 /* update the level sums */ 1097 1087 parent->child_active_sum += (s32)(active - child->active); 1098 1088 parent->child_inuse_sum += (s32)(inuse - child->inuse); 1099 - /* apply the udpates */ 1089 + /* apply the updates */ 1100 1090 child->active = active; 1101 1091 child->inuse = inuse; 1102 1092
+5 -3
block/blk-mq-sched.c
··· 358 358 unsigned int nr_segs) 359 359 { 360 360 struct elevator_queue *e = q->elevator; 361 - struct blk_mq_ctx *ctx = blk_mq_get_ctx(q); 362 - struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, bio->bi_opf, ctx); 361 + struct blk_mq_ctx *ctx; 362 + struct blk_mq_hw_ctx *hctx; 363 363 bool ret = false; 364 364 enum hctx_type type; 365 365 366 366 if (e && e->type->ops.bio_merge) 367 - return e->type->ops.bio_merge(hctx, bio, nr_segs); 367 + return e->type->ops.bio_merge(q, bio, nr_segs); 368 368 369 + ctx = blk_mq_get_ctx(q); 370 + hctx = blk_mq_map_queue(q, bio->bi_opf, ctx); 369 371 type = hctx->type; 370 372 if (!(hctx->flags & BLK_MQ_F_SHOULD_MERGE) || 371 373 list_empty_careful(&ctx->rq_lists[type]))
+7 -4
block/blk-mq.c
··· 2232 2232 /* Bypass scheduler for flush requests */ 2233 2233 blk_insert_flush(rq); 2234 2234 blk_mq_run_hw_queue(data.hctx, true); 2235 - } else if (plug && (q->nr_hw_queues == 1 || q->mq_ops->commit_rqs || 2236 - !blk_queue_nonrot(q))) { 2235 + } else if (plug && (q->nr_hw_queues == 1 || 2236 + blk_mq_is_sbitmap_shared(rq->mq_hctx->flags) || 2237 + q->mq_ops->commit_rqs || !blk_queue_nonrot(q))) { 2237 2238 /* 2238 2239 * Use plugging if we have a ->commit_rqs() hook as well, as 2239 2240 * we know the driver uses bd->last in a smart fashion. ··· 3286 3285 /* tags can _not_ be used after returning from blk_mq_exit_queue */ 3287 3286 void blk_mq_exit_queue(struct request_queue *q) 3288 3287 { 3289 - struct blk_mq_tag_set *set = q->tag_set; 3288 + struct blk_mq_tag_set *set = q->tag_set; 3290 3289 3291 - blk_mq_del_queue_tag_set(q); 3290 + /* Checks hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED. */ 3292 3291 blk_mq_exit_hw_queues(q, set, set->nr_hw_queues); 3292 + /* May clear BLK_MQ_F_TAG_QUEUE_SHARED in hctx->flags. */ 3293 + blk_mq_del_queue_tag_set(q); 3293 3294 } 3294 3295 3295 3296 static int __blk_mq_alloc_rq_maps(struct blk_mq_tag_set *set)
+3 -2
block/kyber-iosched.c
··· 561 561 } 562 562 } 563 563 564 - static bool kyber_bio_merge(struct blk_mq_hw_ctx *hctx, struct bio *bio, 564 + static bool kyber_bio_merge(struct request_queue *q, struct bio *bio, 565 565 unsigned int nr_segs) 566 566 { 567 + struct blk_mq_ctx *ctx = blk_mq_get_ctx(q); 568 + struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, bio->bi_opf, ctx); 567 569 struct kyber_hctx_data *khd = hctx->sched_data; 568 - struct blk_mq_ctx *ctx = blk_mq_get_ctx(hctx->queue); 569 570 struct kyber_ctx_queue *kcq = &khd->kcqs[ctx->index_hw[hctx->type]]; 570 571 unsigned int sched_domain = kyber_sched_domain(bio->bi_opf); 571 572 struct list_head *rq_list = &kcq->rq_list[sched_domain];
+1 -2
block/mq-deadline.c
··· 461 461 return ELEVATOR_NO_MERGE; 462 462 } 463 463 464 - static bool dd_bio_merge(struct blk_mq_hw_ctx *hctx, struct bio *bio, 464 + static bool dd_bio_merge(struct request_queue *q, struct bio *bio, 465 465 unsigned int nr_segs) 466 466 { 467 - struct request_queue *q = hctx->queue; 468 467 struct deadline_data *dd = q->elevator->elevator_data; 469 468 struct request *free = NULL; 470 469 bool ret;
+1 -1
block/partitions/efi.c
··· 682 682 } 683 683 684 684 /** 685 - * efi_partition(struct parsed_partitions *state) 685 + * efi_partition - scan for GPT partitions 686 686 * @state: disk parsed partitions 687 687 * 688 688 * Description: called from check.c, if the disk contains GPT
+5 -5
drivers/block/nbd.c
··· 1980 1980 * config ref and try to destroy the workqueue from inside the work 1981 1981 * queue. 1982 1982 */ 1983 - flush_workqueue(nbd->recv_workq); 1983 + if (nbd->recv_workq) 1984 + flush_workqueue(nbd->recv_workq); 1984 1985 if (test_and_clear_bit(NBD_RT_HAS_CONFIG_REF, 1985 1986 &nbd->config->runtime_flags)) 1986 1987 nbd_config_put(nbd); ··· 2015 2014 return -EINVAL; 2016 2015 } 2017 2016 mutex_unlock(&nbd_index_mutex); 2018 - if (!refcount_inc_not_zero(&nbd->config_refs)) { 2019 - nbd_put(nbd); 2020 - return 0; 2021 - } 2017 + if (!refcount_inc_not_zero(&nbd->config_refs)) 2018 + goto put_nbd; 2022 2019 nbd_disconnect_and_put(nbd); 2023 2020 nbd_config_put(nbd); 2021 + put_nbd: 2024 2022 nbd_put(nbd); 2025 2023 return 0; 2026 2024 }
+2 -1
drivers/nvme/host/core.c
··· 2901 2901 ctrl->hmmaxd = le16_to_cpu(id->hmmaxd); 2902 2902 } 2903 2903 2904 - ret = nvme_mpath_init(ctrl, id); 2904 + ret = nvme_mpath_init_identify(ctrl, id); 2905 2905 if (ret < 0) 2906 2906 goto out_free; 2907 2907 ··· 4364 4364 min(default_ps_max_latency_us, (unsigned long)S32_MAX)); 4365 4365 4366 4366 nvme_fault_inject_init(&ctrl->fault_inject, dev_name(ctrl->device)); 4367 + nvme_mpath_init_ctrl(ctrl); 4367 4368 4368 4369 return 0; 4369 4370 out_free_name:
+29 -26
drivers/nvme/host/multipath.c
··· 781 781 put_disk(head->disk); 782 782 } 783 783 784 - int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id) 784 + void nvme_mpath_init_ctrl(struct nvme_ctrl *ctrl) 785 785 { 786 - int error; 786 + mutex_init(&ctrl->ana_lock); 787 + timer_setup(&ctrl->anatt_timer, nvme_anatt_timeout, 0); 788 + INIT_WORK(&ctrl->ana_work, nvme_ana_work); 789 + } 790 + 791 + int nvme_mpath_init_identify(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id) 792 + { 793 + size_t max_transfer_size = ctrl->max_hw_sectors << SECTOR_SHIFT; 794 + size_t ana_log_size; 795 + int error = 0; 787 796 788 797 /* check if multipath is enabled and we have the capability */ 789 798 if (!multipath || !ctrl->subsys || ··· 804 795 ctrl->nanagrpid = le32_to_cpu(id->nanagrpid); 805 796 ctrl->anagrpmax = le32_to_cpu(id->anagrpmax); 806 797 807 - mutex_init(&ctrl->ana_lock); 808 - timer_setup(&ctrl->anatt_timer, nvme_anatt_timeout, 0); 809 - ctrl->ana_log_size = sizeof(struct nvme_ana_rsp_hdr) + 810 - ctrl->nanagrpid * sizeof(struct nvme_ana_group_desc); 811 - ctrl->ana_log_size += ctrl->max_namespaces * sizeof(__le32); 812 - 813 - if (ctrl->ana_log_size > ctrl->max_hw_sectors << SECTOR_SHIFT) { 798 + ana_log_size = sizeof(struct nvme_ana_rsp_hdr) + 799 + ctrl->nanagrpid * sizeof(struct nvme_ana_group_desc) + 800 + ctrl->max_namespaces * sizeof(__le32); 801 + if (ana_log_size > max_transfer_size) { 814 802 dev_err(ctrl->device, 815 - "ANA log page size (%zd) larger than MDTS (%d).\n", 816 - ctrl->ana_log_size, 817 - ctrl->max_hw_sectors << SECTOR_SHIFT); 803 + "ANA log page size (%zd) larger than MDTS (%zd).\n", 804 + ana_log_size, max_transfer_size); 818 805 dev_err(ctrl->device, "disabling ANA support.\n"); 819 - return 0; 806 + goto out_uninit; 820 807 } 821 - 822 - INIT_WORK(&ctrl->ana_work, nvme_ana_work); 823 - kfree(ctrl->ana_log_buf); 824 - ctrl->ana_log_buf = kmalloc(ctrl->ana_log_size, GFP_KERNEL); 825 - if (!ctrl->ana_log_buf) { 826 - error = -ENOMEM; 827 - goto out; 808 + if (ana_log_size > ctrl->ana_log_size) { 809 + nvme_mpath_stop(ctrl); 810 + kfree(ctrl->ana_log_buf); 811 + ctrl->ana_log_buf = kmalloc(ana_log_size, GFP_KERNEL); 812 + if (!ctrl->ana_log_buf) 813 + return -ENOMEM; 828 814 } 829 - 815 + ctrl->ana_log_size = ana_log_size; 830 816 error = nvme_read_ana_log(ctrl); 831 817 if (error) 832 - goto out_free_ana_log_buf; 818 + goto out_uninit; 833 819 return 0; 834 - out_free_ana_log_buf: 835 - kfree(ctrl->ana_log_buf); 836 - ctrl->ana_log_buf = NULL; 837 - out: 820 + 821 + out_uninit: 822 + nvme_mpath_uninit(ctrl); 838 823 return error; 839 824 } 840 825
+6 -2
drivers/nvme/host/nvme.h
··· 712 712 int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl,struct nvme_ns_head *head); 713 713 void nvme_mpath_add_disk(struct nvme_ns *ns, struct nvme_id_ns *id); 714 714 void nvme_mpath_remove_disk(struct nvme_ns_head *head); 715 - int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id); 715 + int nvme_mpath_init_identify(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id); 716 + void nvme_mpath_init_ctrl(struct nvme_ctrl *ctrl); 716 717 void nvme_mpath_uninit(struct nvme_ctrl *ctrl); 717 718 void nvme_mpath_stop(struct nvme_ctrl *ctrl); 718 719 bool nvme_mpath_clear_current_path(struct nvme_ns *ns); ··· 781 780 static inline void nvme_trace_bio_complete(struct request *req) 782 781 { 783 782 } 784 - static inline int nvme_mpath_init(struct nvme_ctrl *ctrl, 783 + static inline void nvme_mpath_init_ctrl(struct nvme_ctrl *ctrl) 784 + { 785 + } 786 + static inline int nvme_mpath_init_identify(struct nvme_ctrl *ctrl, 785 787 struct nvme_id_ctrl *id) 786 788 { 787 789 if (ctrl->subsys->cmic & NVME_CTRL_CMIC_ANA)
+2 -5
drivers/nvme/target/admin-cmd.c
··· 975 975 case nvme_admin_keep_alive: 976 976 req->execute = nvmet_execute_keep_alive; 977 977 return 0; 978 + default: 979 + return nvmet_report_invalid_opcode(req); 978 980 } 979 - 980 - pr_debug("unhandled cmd %d on qid %d\n", cmd->common.opcode, 981 - req->sq->qid); 982 - req->error_loc = offsetof(struct nvme_common_command, opcode); 983 - return NVME_SC_INVALID_OPCODE | NVME_SC_DNR; 984 981 }
+1 -1
drivers/nvme/target/discovery.c
··· 379 379 req->execute = nvmet_execute_disc_identify; 380 380 return 0; 381 381 default: 382 - pr_err("unhandled cmd %d\n", cmd->common.opcode); 382 + pr_debug("unhandled cmd %d\n", cmd->common.opcode); 383 383 req->error_loc = offsetof(struct nvme_common_command, opcode); 384 384 return NVME_SC_INVALID_OPCODE | NVME_SC_DNR; 385 385 }
+3 -3
drivers/nvme/target/fabrics-cmd.c
··· 94 94 req->execute = nvmet_execute_prop_get; 95 95 break; 96 96 default: 97 - pr_err("received unknown capsule type 0x%x\n", 97 + pr_debug("received unknown capsule type 0x%x\n", 98 98 cmd->fabrics.fctype); 99 99 req->error_loc = offsetof(struct nvmf_common_command, fctype); 100 100 return NVME_SC_INVALID_OPCODE | NVME_SC_DNR; ··· 284 284 struct nvme_command *cmd = req->cmd; 285 285 286 286 if (!nvme_is_fabrics(cmd)) { 287 - pr_err("invalid command 0x%x on unconnected queue.\n", 287 + pr_debug("invalid command 0x%x on unconnected queue.\n", 288 288 cmd->fabrics.opcode); 289 289 req->error_loc = offsetof(struct nvme_common_command, opcode); 290 290 return NVME_SC_INVALID_OPCODE | NVME_SC_DNR; 291 291 } 292 292 if (cmd->fabrics.fctype != nvme_fabrics_type_connect) { 293 - pr_err("invalid capsule type 0x%x on unconnected queue.\n", 293 + pr_debug("invalid capsule type 0x%x on unconnected queue.\n", 294 294 cmd->fabrics.fctype); 295 295 req->error_loc = offsetof(struct nvmf_common_command, fctype); 296 296 return NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
+1 -1
drivers/nvme/target/io-cmd-bdev.c
··· 258 258 259 259 sector = nvmet_lba_to_sect(req->ns, req->cmd->rw.slba); 260 260 261 - if (req->transfer_len <= NVMET_MAX_INLINE_DATA_LEN) { 261 + if (nvmet_use_inline_bvec(req)) { 262 262 bio = &req->b.inline_bio; 263 263 bio_init(bio, req->inline_bvec, ARRAY_SIZE(req->inline_bvec)); 264 264 } else {
+5 -3
drivers/nvme/target/io-cmd-file.c
··· 49 49 50 50 ns->file = filp_open(ns->device_path, flags, 0); 51 51 if (IS_ERR(ns->file)) { 52 - pr_err("failed to open file %s: (%ld)\n", 53 - ns->device_path, PTR_ERR(ns->file)); 54 - return PTR_ERR(ns->file); 52 + ret = PTR_ERR(ns->file); 53 + pr_err("failed to open file %s: (%d)\n", 54 + ns->device_path, ret); 55 + ns->file = NULL; 56 + return ret; 55 57 } 56 58 57 59 ret = nvmet_file_ns_revalidate(ns);
+6
drivers/nvme/target/nvmet.h
··· 616 616 return le64_to_cpu(lba) << (ns->blksize_shift - SECTOR_SHIFT); 617 617 } 618 618 619 + static inline bool nvmet_use_inline_bvec(struct nvmet_req *req) 620 + { 621 + return req->transfer_len <= NVMET_MAX_INLINE_DATA_LEN && 622 + req->sg_cnt <= NVMET_MAX_INLINE_BIOVEC; 623 + } 624 + 619 625 #endif /* _NVMET_H */
+1 -1
drivers/nvme/target/passthru.c
··· 194 194 if (req->sg_cnt > BIO_MAX_VECS) 195 195 return -EINVAL; 196 196 197 - if (req->transfer_len <= NVMET_MAX_INLINE_DATA_LEN) { 197 + if (nvmet_use_inline_bvec(req)) { 198 198 bio = &req->p.inline_bio; 199 199 bio_init(bio, req->inline_bvec, ARRAY_SIZE(req->inline_bvec)); 200 200 } else {
+2 -2
drivers/nvme/target/rdma.c
··· 700 700 { 701 701 struct nvmet_rdma_rsp *rsp = 702 702 container_of(wc->wr_cqe, struct nvmet_rdma_rsp, send_cqe); 703 - struct nvmet_rdma_queue *queue = cq->cq_context; 703 + struct nvmet_rdma_queue *queue = wc->qp->qp_context; 704 704 705 705 nvmet_rdma_release_rsp(rsp); 706 706 ··· 786 786 { 787 787 struct nvmet_rdma_rsp *rsp = 788 788 container_of(wc->wr_cqe, struct nvmet_rdma_rsp, write_cqe); 789 - struct nvmet_rdma_queue *queue = cq->cq_context; 789 + struct nvmet_rdma_queue *queue = wc->qp->qp_context; 790 790 struct rdma_cm_id *cm_id = rsp->queue->cm_id; 791 791 u16 status; 792 792
-5
include/linux/blkdev.h
··· 676 676 extern void blk_set_pm_only(struct request_queue *q); 677 677 extern void blk_clear_pm_only(struct request_queue *q); 678 678 679 - static inline bool blk_account_rq(struct request *rq) 680 - { 681 - return (rq->rq_flags & RQF_STARTED) && !blk_rq_is_passthrough(rq); 682 - } 683 - 684 679 #define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist) 685 680 686 681 #define rq_data_dir(rq) (op_is_write(req_op(rq)) ? WRITE : READ)
+1 -1
include/linux/elevator.h
··· 34 34 void (*depth_updated)(struct blk_mq_hw_ctx *); 35 35 36 36 bool (*allow_merge)(struct request_queue *, struct request *, struct bio *); 37 - bool (*bio_merge)(struct blk_mq_hw_ctx *, struct bio *, unsigned int); 37 + bool (*bio_merge)(struct request_queue *, struct bio *, unsigned int); 38 38 int (*request_merge)(struct request_queue *q, struct request **, struct bio *); 39 39 void (*request_merged)(struct request_queue *, struct request *, enum elv_merge); 40 40 void (*requests_merged)(struct request_queue *, struct request *, struct request *);
+1 -1
include/uapi/linux/fs.h
··· 185 185 #define BLKROTATIONAL _IO(0x12,126) 186 186 #define BLKZEROOUT _IO(0x12,127) 187 187 /* 188 - * A jump here: 130-131 are reserved for zoned block devices 188 + * A jump here: 130-136 are reserved for zoned block devices 189 189 * (see uapi/linux/blkzoned.h) 190 190 */ 191 191