The backing device information only makes sense for file system I/O, and thus belongs into the gendisk and not the lower level request_queue structure. Move it there.
Unified · Split
| @@ -5266,8 +5266,8 @@ bfq_set_next_ioprio_data(struct bfq_queue *bfqq, struct bfq_io_cq *bic) · 5265 unmodified lines | ||
| 5266 | 5266 | switch (ioprio_class) { |
| 5267 | 5267 | default: |
| 5268 | 5268 | pr_err("bdi %s: bfq: bad prio class %d\n", |
| 5269 | − bdi_dev_name(bfqq->bfqd->queue->backing_dev_info), | |
| 5270 | − ioprio_class); | |
| 5269 | + bdi_dev_name(queue_to_disk(bfqq->bfqd->queue)->bdi), | |
| 5270 | + ioprio_class); | |
| 5271 | 5271 | fallthrough; |
| 5272 | 5272 | case IOPRIO_CLASS_NONE: |
| 5273 | 5273 | /* |
| @@ -489,10 +489,9 @@ static int blkcg_reset_stats(struct cgroup_subsys_state *css, · 488 unmodified lines | ||
| 489 | 489 | |
| 490 | 490 | const char *blkg_dev_name(struct blkcg_gq *blkg) |
| 491 | 491 | { |
| 492 | − /* some drivers (floppy) instantiate a queue w/o disk registered */ | |
| 493 | − if (blkg->q->backing_dev_info->dev) | |
| 494 | − return bdi_dev_name(blkg->q->backing_dev_info); | |
| 495 | − return NULL; | |
| 492 | + if (!queue_has_disk(blkg->q) || !queue_to_disk(blkg->q)->bdi->dev) | |
| 493 | + return NULL; | |
| 494 | + return bdi_dev_name(queue_to_disk(blkg->q)->bdi); | |
| 496 | 495 | } |
| 497 | 496 | |
| 498 | 497 | /** |
| @@ -14,7 +14,6 @@ · 13 unmodified lines | ||
| 14 | 14 | */ |
| 15 | 15 | #include <linux/kernel.h> |
| 16 | 16 | #include <linux/module.h> |
| 17 | −#include <linux/backing-dev.h> | |
| 18 | 17 | #include <linux/bio.h> |
| 19 | 18 | #include <linux/blkdev.h> |
| 20 | 19 | #include <linux/blk-mq.h> |
| @@ -531,13 +530,9 @@ struct request_queue *blk_alloc_queue(int node_id) · 510 unmodified lines | ||
| 531 | 530 | if (ret) |
| 532 | 531 | goto fail_id; |
| 533 | 532 | |
| 534 | − q->backing_dev_info = bdi_alloc(node_id); | |
| 535 | − if (!q->backing_dev_info) | |
| 536 | − goto fail_split; | |
| 537 | − | |
| 538 | 533 | q->stats = blk_alloc_queue_stats(); |
| 539 | 534 | if (!q->stats) |
| 540 | − goto fail_stats; | |
| 535 | + goto fail_split; | |
| 541 | 536 | |
| 542 | 537 | q->node = node_id; |
| 543 | 538 | |
| @@ -567,7 +562,7 @@ struct request_queue *blk_alloc_queue(int node_id) · 23 unmodified lines | ||
| 567 | 562 | if (percpu_ref_init(&q->q_usage_counter, |
| 568 | 563 | blk_queue_usage_counter_release, |
| 569 | 564 | PERCPU_REF_INIT_ATOMIC, GFP_KERNEL)) |
| 570 | − goto fail_bdi; | |
| 565 | + goto fail_stats; | |
| 571 | 566 | |
| 572 | 567 | if (blkcg_init_queue(q)) |
| 573 | 568 | goto fail_ref; |
| @@ -580,10 +575,8 @@ struct request_queue *blk_alloc_queue(int node_id) · 6 unmodified lines | ||
| 580 | 575 | |
| 581 | 576 | fail_ref: |
| 582 | 577 | percpu_ref_exit(&q->q_usage_counter); |
| 583 | −fail_bdi: | |
| 584 | − blk_free_queue_stats(q->stats); | |
| 585 | 578 | fail_stats: |
| 586 | − bdi_put(q->backing_dev_info); | |
| 579 | + blk_free_queue_stats(q->stats); | |
| 587 | 580 | fail_split: |
| 588 | 581 | bioset_exit(&q->bio_split); |
| 589 | 582 | fail_id: |
| @@ -525,7 +525,7 @@ void blk_mq_free_request(struct request *rq) · 524 unmodified lines | ||
| 525 | 525 | __blk_mq_dec_active_requests(hctx); |
| 526 | 526 | |
| 527 | 527 | if (unlikely(laptop_mode && !blk_rq_is_passthrough(rq))) |
| 528 | − laptop_io_completion(q->backing_dev_info); | |
| 528 | + laptop_io_completion(queue_to_disk(q)->bdi); | |
| 529 | 529 | |
| 530 | 530 | rq_qos_done(q, rq); |
| 531 | 531 | |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | #include <linux/bio.h> |
| 9 | 9 | #include <linux/blkdev.h> |
| 10 | 10 | #include <linux/pagemap.h> |
| 11 | +#include <linux/backing-dev-defs.h> | |
| 11 | 12 | #include <linux/gcd.h> |
| 12 | 13 | #include <linux/lcm.h> |
| 13 | 14 | #include <linux/jiffies.h> |
| @@ -140,7 +141,9 @@ void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_secto · 126 unmodified lines | ||
| 140 | 141 | limits->logical_block_size >> SECTOR_SHIFT); |
| 141 | 142 | limits->max_sectors = max_sectors; |
| 142 | 143 | |
| 143 | − q->backing_dev_info->io_pages = max_sectors >> (PAGE_SHIFT - 9); | |
| 144 | + if (!queue_has_disk(q)) | |
| 145 | + return; | |
| 146 | + queue_to_disk(q)->bdi->io_pages = max_sectors >> (PAGE_SHIFT - 9); | |
| 144 | 147 | } |
| 145 | 148 | EXPORT_SYMBOL(blk_queue_max_hw_sectors); |
| 146 | 149 | |
| @@ -388,10 +391,9 @@ void disk_update_readahead(struct gendisk *disk) · 241 unmodified lines | ||
| 388 | 391 | * For read-ahead of large files to be effective, we need to read ahead |
| 389 | 392 | * at least twice the optimal I/O size. |
| 390 | 393 | */ |
| 391 | − q->backing_dev_info->ra_pages = | |
| 394 | + disk->bdi->ra_pages = | |
| 392 | 395 | max(queue_io_opt(q) * 2 / PAGE_SIZE, VM_READAHEAD_PAGES); |
| 393 | − q->backing_dev_info->io_pages = | |
| 394 | − queue_max_sectors(q) >> (PAGE_SHIFT - 9); | |
| 396 | + disk->bdi->io_pages = queue_max_sectors(q) >> (PAGE_SHIFT - 9); | |
| 395 | 397 | } |
| 396 | 398 | EXPORT_SYMBOL_GPL(disk_update_readahead); |
| 397 | 399 | |
| @@ -473,7 +475,9 @@ EXPORT_SYMBOL(blk_limits_io_opt); · 75 unmodified lines | ||
| 473 | 475 | void blk_queue_io_opt(struct request_queue *q, unsigned int opt) |
| 474 | 476 | { |
| 475 | 477 | blk_limits_io_opt(&q->limits, opt); |
| 476 | − q->backing_dev_info->ra_pages = | |
| 478 | + if (!queue_has_disk(q)) | |
| 479 | + return; | |
| 480 | + queue_to_disk(q)->bdi->ra_pages = | |
| 477 | 481 | max(queue_io_opt(q) * 2 / PAGE_SIZE, VM_READAHEAD_PAGES); |
| 478 | 482 | } |
| 479 | 483 | EXPORT_SYMBOL(blk_queue_io_opt); |
| @@ -88,9 +88,11 @@ queue_requests_store(struct request_queue *q, const char *page, size_t count) · 87 unmodified lines | ||
| 88 | 88 | |
| 89 | 89 | static ssize_t queue_ra_show(struct request_queue *q, char *page) |
| 90 | 90 | { |
| 91 | − unsigned long ra_kb = q->backing_dev_info->ra_pages << | |
| 92 | − (PAGE_SHIFT - 10); | |
| 91 | + unsigned long ra_kb; | |
| 93 | 92 | |
| 93 | + if (!queue_has_disk(q)) | |
| 94 | + return -EINVAL; | |
| 95 | + ra_kb = queue_to_disk(q)->bdi->ra_pages << (PAGE_SHIFT - 10); | |
| 94 | 96 | return queue_var_show(ra_kb, page); |
| 95 | 97 | } |
| 96 | 98 | |
| @@ -98,13 +100,14 @@ static ssize_t · 1 unmodified line | ||
| 98 | 100 | queue_ra_store(struct request_queue *q, const char *page, size_t count) |
| 99 | 101 | { |
| 100 | 102 | unsigned long ra_kb; |
| 101 | − ssize_t ret = queue_var_store(&ra_kb, page, count); | |
| 103 | + ssize_t ret; | |
| 102 | 104 | |
| 105 | + if (!queue_has_disk(q)) | |
| 106 | + return -EINVAL; | |
| 107 | + ret = queue_var_store(&ra_kb, page, count); | |
| 103 | 108 | if (ret < 0) |
| 104 | 109 | return ret; |
| 105 | − | |
| 106 | − q->backing_dev_info->ra_pages = ra_kb >> (PAGE_SHIFT - 10); | |
| 107 | − | |
| 110 | + queue_to_disk(q)->bdi->ra_pages = ra_kb >> (PAGE_SHIFT - 10); | |
| 108 | 111 | return ret; |
| 109 | 112 | } |
| 110 | 113 | |
| @@ -251,7 +254,9 @@ queue_max_sectors_store(struct request_queue *q, const char *page, size_t count) · 140 unmodified lines | ||
| 251 | 254 | |
| 252 | 255 | spin_lock_irq(&q->queue_lock); |
| 253 | 256 | q->limits.max_sectors = max_sectors_kb << 1; |
| 254 | − q->backing_dev_info->io_pages = max_sectors_kb >> (PAGE_SHIFT - 10); | |
| 257 | + if (queue_has_disk(q)) | |
| 258 | + queue_to_disk(q)->bdi->io_pages = | |
| 259 | + max_sectors_kb >> (PAGE_SHIFT - 10); | |
| 255 | 260 | spin_unlock_irq(&q->queue_lock); |
| 256 | 261 | |
| 257 | 262 | return ret; |
| @@ -766,13 +771,6 @@ static void blk_exit_queue(struct request_queue *q) · 508 unmodified lines | ||
| 766 | 771 | * e.g. blkcg_print_blkgs() to crash. |
| 767 | 772 | */ |
| 768 | 773 | blkcg_exit_queue(q); |
| 769 | − | |
| 770 | − /* | |
| 771 | − * Since the cgroup code may dereference the @q->backing_dev_info | |
| 772 | − * pointer, only decrease its reference count after having removed the | |
| 773 | − * association with the block cgroup controller. | |
| 774 | − */ | |
| 775 | − bdi_put(q->backing_dev_info); | |
| 776 | 774 | } |
| 777 | 775 | |
| 778 | 776 | /** |
| @@ -97,7 +97,7 @@ static void wb_timestamp(struct rq_wb *rwb, unsigned long *var) · 96 unmodified lines | ||
| 97 | 97 | */ |
| 98 | 98 | static bool wb_recent_wait(struct rq_wb *rwb) |
| 99 | 99 | { |
| 100 | − struct bdi_writeback *wb = &rwb->rqos.q->backing_dev_info->wb; | |
| 100 | + struct bdi_writeback *wb = &queue_to_disk(rwb->rqos.q)->bdi->wb; | |
| 101 | 101 | |
| 102 | 102 | return time_before(jiffies, wb->dirty_sleep + HZ); |
| 103 | 103 | } |
| @@ -234,7 +234,7 @@ enum { · 130 unmodified lines | ||
| 234 | 234 | |
| 235 | 235 | static int latency_exceeded(struct rq_wb *rwb, struct blk_rq_stat *stat) |
| 236 | 236 | { |
| 237 | − struct backing_dev_info *bdi = rwb->rqos.q->backing_dev_info; | |
| 237 | + struct backing_dev_info *bdi = queue_to_disk(rwb->rqos.q)->bdi; | |
| 238 | 238 | struct rq_depth *rqd = &rwb->rq_depth; |
| 239 | 239 | u64 thislat; |
| 240 | 240 | |
| @@ -287,7 +287,7 @@ static int latency_exceeded(struct rq_wb *rwb, struct blk_rq_stat *stat) · 46 unmodified lines | ||
| 287 | 287 | |
| 288 | 288 | static void rwb_trace_step(struct rq_wb *rwb, const char *msg) |
| 289 | 289 | { |
| 290 | − struct backing_dev_info *bdi = rwb->rqos.q->backing_dev_info; | |
| 290 | + struct backing_dev_info *bdi = queue_to_disk(rwb->rqos.q)->bdi; | |
| 291 | 291 | struct rq_depth *rqd = &rwb->rq_depth; |
| 292 | 292 | |
| 293 | 293 | trace_wbt_step(bdi, msg, rqd->scale_step, rwb->cur_win_nsec, |
| @@ -359,8 +359,8 @@ static void wb_timer_fn(struct blk_stat_callback *cb) · 65 unmodified lines | ||
| 359 | 359 | |
| 360 | 360 | status = latency_exceeded(rwb, cb->stat); |
| 361 | 361 | |
| 362 | − trace_wbt_timer(rwb->rqos.q->backing_dev_info, status, rqd->scale_step, | |
| 363 | − inflight); | |
| 362 | + trace_wbt_timer(queue_to_disk(rwb->rqos.q)->bdi, status, | |
| 363 | + rqd->scale_step, inflight); | |
| 364 | 364 | |
| 365 | 365 | /* |
| 366 | 366 | * If we exceeded the latency target, step down. If we did not, |
| @@ -466,10 +466,9 @@ static void register_disk(struct device *parent, struct gendisk *disk, · 465 unmodified lines | ||
| 466 | 466 | dev_set_uevent_suppress(ddev, 0); |
| 467 | 467 | disk_uevent(disk, KOBJ_ADD); |
| 468 | 468 | |
| 469 | − if (disk->queue->backing_dev_info->dev) { | |
| 470 | − err = sysfs_create_link(&ddev->kobj, | |
| 471 | − &disk->queue->backing_dev_info->dev->kobj, | |
| 472 | − "bdi"); | |
| 469 | + if (disk->bdi->dev) { | |
| 470 | + err = sysfs_create_link(&ddev->kobj, &disk->bdi->dev->kobj, | |
| 471 | + "bdi"); | |
| 473 | 472 | WARN_ON(err); |
| 474 | 473 | } |
| 475 | 474 | } |
| @@ -540,15 +539,14 @@ void device_add_disk(struct device *parent, struct gendisk *disk, · 64 unmodified lines | ||
| 540 | 539 | disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO; |
| 541 | 540 | disk->flags |= GENHD_FL_NO_PART_SCAN; |
| 542 | 541 | } else { |
| 543 | − struct backing_dev_info *bdi = disk->queue->backing_dev_info; | |
| 544 | 542 | struct device *dev = disk_to_dev(disk); |
| 545 | 543 | |
| 546 | 544 | /* Register BDI before referencing it from bdev */ |
| 547 | 545 | dev->devt = MKDEV(disk->major, disk->first_minor); |
| 548 | − ret = bdi_register(bdi, "%u:%u", | |
| 546 | + ret = bdi_register(disk->bdi, "%u:%u", | |
| 549 | 547 | disk->major, disk->first_minor); |
| 550 | 548 | WARN_ON(ret); |
| 551 | − bdi_set_owner(bdi, dev); | |
| 549 | + bdi_set_owner(disk->bdi, dev); | |
| 552 | 550 | bdev_add(disk->part0, dev->devt); |
| 553 | 551 | } |
| 554 | 552 | register_disk(parent, disk, groups); |
| @@ -615,7 +613,7 @@ void del_gendisk(struct gendisk *disk) · 60 unmodified lines | ||
| 615 | 613 | * Unregister bdi before releasing device numbers (as they can |
| 616 | 614 | * get reused and we'd get clashes in sysfs). |
| 617 | 615 | */ |
| 618 | − bdi_unregister(disk->queue->backing_dev_info); | |
| 616 | + bdi_unregister(disk->bdi); | |
| 619 | 617 | } |
| 620 | 618 | |
| 621 | 619 | blk_unregister_queue(disk); |
| @@ -1088,6 +1086,7 @@ static void disk_release(struct device *dev) · 466 unmodified lines | ||
| 1088 | 1086 | |
| 1089 | 1087 | might_sleep(); |
| 1090 | 1088 | |
| 1089 | + bdi_put(disk->bdi); | |
| 1091 | 1090 | if (MAJOR(dev->devt) == BLOCK_EXT_MAJOR) |
| 1092 | 1091 | blk_free_ext_minor(MINOR(dev->devt)); |
| 1093 | 1092 | disk_release_events(disk); |
| @@ -1268,9 +1267,13 @@ struct gendisk *__alloc_disk_node(int minors, int node_id) · 174 unmodified lines | ||
| 1268 | 1267 | if (!disk) |
| 1269 | 1268 | return NULL; |
| 1270 | 1269 | |
| 1270 | + disk->bdi = bdi_alloc(node_id); | |
| 1271 | + if (!disk->bdi) | |
| 1272 | + goto out_free_disk; | |
| 1273 | + | |
| 1271 | 1274 | disk->part0 = bdev_alloc(disk, 0); |
| 1272 | 1275 | if (!disk->part0) |
| 1273 | − goto out_free_disk; | |
| 1276 | + goto out_free_bdi; | |
| 1274 | 1277 | |
| 1275 | 1278 | disk->node_id = node_id; |
| 1276 | 1279 | mutex_init(&disk->open_mutex); |
| @@ -1292,6 +1295,8 @@ struct gendisk *__alloc_disk_node(int minors, int node_id) · 15 unmodified lines | ||
| 1292 | 1295 | out_destroy_part_tbl: |
| 1293 | 1296 | xa_destroy(&disk->part_tbl); |
| 1294 | 1297 | iput(disk->part0->bd_inode); |
| 1298 | +out_free_bdi: | |
| 1299 | + bdi_put(disk->bdi); | |
| 1295 | 1300 | out_free_disk: |
| 1296 | 1301 | kfree(disk); |
| 1297 | 1302 | return NULL; |
| @@ -905,13 +905,12 @@ static bool drbd_may_do_local_read(struct drbd_device *device, sector_t sector, · 904 unmodified lines | ||
| 905 | 905 | static bool remote_due_to_read_balancing(struct drbd_device *device, sector_t sector, |
| 906 | 906 | enum drbd_read_balancing rbm) |
| 907 | 907 | { |
| 908 | − struct backing_dev_info *bdi; | |
| 909 | 908 | int stripe_shift; |
| 910 | 909 | |
| 911 | 910 | switch (rbm) { |
| 912 | 911 | case RB_CONGESTED_REMOTE: |
| 913 | − bdi = device->ldev->backing_bdev->bd_disk->queue->backing_dev_info; | |
| 914 | − return bdi_read_congested(bdi); | |
| 912 | + return bdi_read_congested( | |
| 913 | + device->ldev->backing_bdev->bd_disk->bdi); | |
| 915 | 914 | case RB_LEAST_PENDING: |
| 916 | 915 | return atomic_read(&device->local_cnt) > |
| 917 | 916 | atomic_read(&device->ap_pending_cnt) + atomic_read(&device->rs_pending_cnt); |
| @@ -1183,10 +1183,8 @@ try_next_bio: · 1182 unmodified lines | ||
| 1183 | 1183 | wakeup = (pd->write_congestion_on > 0 |
| 1184 | 1184 | && pd->bio_queue_size <= pd->write_congestion_off); |
| 1185 | 1185 | spin_unlock(&pd->lock); |
| 1186 | − if (wakeup) { | |
| 1187 | − clear_bdi_congested(pd->disk->queue->backing_dev_info, | |
| 1188 | − BLK_RW_ASYNC); | |
| 1189 | − } | |
| 1186 | + if (wakeup) | |
| 1187 | + clear_bdi_congested(pd->disk->bdi, BLK_RW_ASYNC); | |
| 1190 | 1188 | |
| 1191 | 1189 | pkt->sleep_time = max(PACKET_WAIT_TIME, 1); |
| 1192 | 1190 | pkt_set_state(pkt, PACKET_WAITING_STATE); |
| @@ -2366,7 +2364,7 @@ static void pkt_make_request_write(struct request_queue *q, struct bio *bio) · 1173 unmodified lines | ||
| 2366 | 2364 | spin_lock(&pd->lock); |
| 2367 | 2365 | if (pd->write_congestion_on > 0 |
| 2368 | 2366 | && pd->bio_queue_size >= pd->write_congestion_on) { |
| 2369 | − set_bdi_congested(q->backing_dev_info, BLK_RW_ASYNC); | |
| 2367 | + set_bdi_congested(bio->bi_bdev->bd_disk->bdi, BLK_RW_ASYNC); | |
| 2370 | 2368 | do { |
| 2371 | 2369 | spin_unlock(&pd->lock); |
| 2372 | 2370 | congestion_wait(BLK_RW_ASYNC, HZ); |
| @@ -1087,7 +1087,7 @@ static int blkdev_get_whole(struct block_device *bdev, fmode_t mode) · 1086 unmodified lines | ||
| 1087 | 1087 | if (!bdev->bd_openers) { |
| 1088 | 1088 | set_init_blocksize(bdev); |
| 1089 | 1089 | if (bdev->bd_bdi == &noop_backing_dev_info) |
| 1090 | − bdev->bd_bdi = bdi_get(disk->queue->backing_dev_info); | |
| 1090 | + bdev->bd_bdi = bdi_get(disk->bdi); | |
| 1091 | 1091 | } |
| 1092 | 1092 | if (test_bit(GD_NEED_PART_SCAN, &disk->state)) |
| 1093 | 1093 | bdev_disk_changed(disk, false); |
| @@ -1122,7 +1122,7 @@ static int blkdev_get_part(struct block_device *part, fmode_t mode) · 28 unmodified lines | ||
| 1122 | 1122 | disk->open_partitions++; |
| 1123 | 1123 | set_init_blocksize(part); |
| 1124 | 1124 | if (part->bd_bdi == &noop_backing_dev_info) |
| 1125 | − part->bd_bdi = bdi_get(disk->queue->backing_dev_info); | |
| 1125 | + part->bd_bdi = bdi_get(disk->bdi); | |
| 1126 | 1126 | done: |
| 1127 | 1127 | part->bd_openers++; |
| 1128 | 1128 | return 0; |
| @@ -5,6 +5,7 @@ · 4 unmodified lines | ||
| 5 | 5 | |
| 6 | 6 | #include <linux/blkdev.h> |
| 7 | 7 | #include <linux/sched/signal.h> |
| 8 | +#include <linux/backing-dev-defs.h> | |
| 8 | 9 | #include "fat.h" |
| 9 | 10 | |
| 10 | 11 | struct fatent_operations { |
| @@ -11,7 +11,6 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/minmax.h> |
| 12 | 12 | #include <linux/timer.h> |
| 13 | 13 | #include <linux/workqueue.h> |
| 14 | −#include <linux/backing-dev-defs.h> | |
| 15 | 14 | #include <linux/wait.h> |
| 16 | 15 | #include <linux/mempool.h> |
| 17 | 16 | #include <linux/pfn.h> |
| @@ -398,8 +397,6 @@ struct request_queue { · 380 unmodified lines | ||
| 398 | 397 | struct blk_mq_hw_ctx **queue_hw_ctx; |
| 399 | 398 | unsigned int nr_hw_queues; |
| 400 | 399 | |
| 401 | − struct backing_dev_info *backing_dev_info; | |
| 402 | − | |
| 403 | 400 | /* |
| 404 | 401 | * The queue owner gets to use this for whatever they like. |
| 405 | 402 | * ll_rw_blk doesn't touch it. |
| @@ -158,6 +158,7 @@ struct gendisk { · 157 unmodified lines | ||
| 158 | 158 | struct mutex open_mutex; /* open/close mutex */ |
| 159 | 159 | unsigned open_partitions; /* number of open partitions */ |
| 160 | 160 | |
| 161 | + struct backing_dev_info *bdi; | |
| 161 | 162 | struct kobject *slave_dir; |
| 162 | 163 | #ifdef CONFIG_BLOCK_HOLDER_DEPRECATED |
| 163 | 164 | struct list_head slave_bdevs; |