Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 deletions block/bfq-cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -550,13 +550,20 @@ static void bfq_pd_init(struct blkg_policy_data *pd)
bfqg->rq_pos_tree = RB_ROOT;
}

static void bfq_pd_free(struct blkg_policy_data *pd)
static void bfqg_release(struct rcu_head *rcu)
{
struct blkg_policy_data *pd =
container_of(rcu, struct blkg_policy_data, rcu_head);
struct bfq_group *bfqg = pd_to_bfqg(pd);

bfqg_put(bfqg);
}

static void bfq_pd_free(struct blkg_policy_data *pd)
{
call_rcu(&pd->rcu_head, bfqg_release);
}

static void bfq_pd_reset_stats(struct blkg_policy_data *pd)
{
struct bfq_group *bfqg = pd_to_bfqg(pd);
Expand Down Expand Up @@ -936,14 +943,23 @@ static void bfq_pd_offline(struct blkg_policy_data *pd)

void bfq_end_wr_async(struct bfq_data *bfqd)
{
struct request_queue *q = bfqd->queue;
struct blkcg_gq *blkg;

list_for_each_entry(blkg, &bfqd->queue->blkg_list, q_node) {
mutex_lock(&q->blkcg_mutex);
spin_lock_irq(&q->queue_lock);
spin_lock(&bfqd->lock);

list_for_each_entry(blkg, &q->blkg_list, q_node) {
struct bfq_group *bfqg = blkg_to_bfqg(blkg);

bfq_end_wr_async_queues(bfqd, bfqg);
}
bfq_end_wr_async_queues(bfqd, bfqd->root_group);

spin_unlock(&bfqd->lock);
spin_unlock_irq(&q->queue_lock);
mutex_unlock(&q->blkcg_mutex);
}

static int bfq_io_show_weight_legacy(struct seq_file *sf, void *v)
Expand Down Expand Up @@ -1147,16 +1163,18 @@ static u64 bfqg_prfill_stat_recursive(struct seq_file *sf,
struct cgroup_subsys_state *pos_css;
u64 sum = 0;

lockdep_assert_held(&blkg->q->queue_lock);

rcu_read_lock();
blkg_for_each_descendant_pre(pos_blkg, pos_css, blkg) {
struct blkg_policy_data *pd;
struct bfq_stat *stat;

if (!pos_blkg->online)
continue;

stat = (void *)blkg_to_pd(pos_blkg, &blkcg_policy_bfq) + off;
pd = blkg_to_pd(pos_blkg, &blkcg_policy_bfq);
if (!pd)
continue;
stat = (void *)pd + off;
sum += bfq_stat_read(stat) + atomic64_read(&stat->aux_cnt);
}
rcu_read_unlock();
Expand Down Expand Up @@ -1416,7 +1434,9 @@ void bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio) {}

void bfq_end_wr_async(struct bfq_data *bfqd)
{
spin_lock_irq(&bfqd->lock);
bfq_end_wr_async_queues(bfqd, bfqd->root_group);
spin_unlock_irq(&bfqd->lock);
}

struct bfq_group *bfq_bio_bfqg(struct bfq_data *bfqd, struct bio *bio)
Expand Down
8 changes: 2 additions & 6 deletions block/bfq-iosched.c
Original file line number Diff line number Diff line change
Expand Up @@ -2653,9 +2653,10 @@ static void bfq_end_wr(struct bfq_data *bfqd)
}
list_for_each_entry(bfqq, &bfqd->idle_list, bfqq_list)
bfq_bfqq_end_wr(bfqq);
bfq_end_wr_async(bfqd);

spin_unlock_irq(&bfqd->lock);

bfq_end_wr_async(bfqd);
}

static sector_t bfq_io_struct_pos(void *io_struct, bool request)
Expand Down Expand Up @@ -7203,10 +7204,7 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_queue *eq)
return -ENOMEM;

eq->elevator_data = bfqd;

spin_lock_irq(&q->queue_lock);
q->elevator = eq;
spin_unlock_irq(&q->queue_lock);

/*
* Our fallback bfqq if bfq_find_alloc_queue() runs into OOM issues.
Expand Down Expand Up @@ -7239,7 +7237,6 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_queue *eq)
* If the disk supports multiple actuators, copy independent
* access ranges from the request queue structure.
*/
spin_lock_irq(&q->queue_lock);
if (ia_ranges) {
/*
* Check if the disk ia_ranges size exceeds the current bfq
Expand All @@ -7265,7 +7262,6 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_queue *eq)
bfqd->sector[0] = 0;
bfqd->nr_sectors[0] = get_capacity(q->disk);
}
spin_unlock_irq(&q->queue_lock);

INIT_LIST_HEAD(&bfqd->dispatch);

Expand Down
2 changes: 1 addition & 1 deletion block/bio-integrity-auto.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ void bio_integrity_prep(struct bio *bio, unsigned int action)
bio_integrity_init(bio, &bid->bip, &bid->bvec, 1);
bid->bio = bio;
bid->bip.bip_flags |= BIP_BLOCK_INTEGRITY;
bio_integrity_alloc_buf(bio, action & BI_ACT_ZERO);
bio_integrity_alloc_buf(bio, GFP_NOIO, action & BI_ACT_ZERO);
if (action & BI_ACT_CHECK)
bio_integrity_setup_default(bio);

Expand Down
4 changes: 2 additions & 2 deletions block/bio-integrity-fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ unsigned int fs_bio_integrity_alloc(struct bio *bio)
if (!action)
return 0;

iib = mempool_alloc(&fs_bio_integrity_pool, GFP_NOIO);
iib = mempool_alloc(&fs_bio_integrity_pool, GFP_NOFS);
bio_integrity_init(bio, &iib->bip, &iib->bvec, 1);

bio_integrity_alloc_buf(bio, action & BI_ACT_ZERO);
bio_integrity_alloc_buf(bio, GFP_NOFS, action & BI_ACT_ZERO);
if (action & BI_ACT_CHECK)
bio_integrity_setup_default(bio);
return action;
Expand Down
9 changes: 4 additions & 5 deletions block/bio-integrity.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ unsigned int __bio_integrity_action(struct bio *bio)
}
return BI_ACT_BUFFER | BI_ACT_CHECK;
case REQ_OP_WRITE:
case REQ_OP_ZONE_APPEND:
/*
* Flush masquerading as write?
*/
Expand All @@ -64,20 +65,18 @@ unsigned int __bio_integrity_action(struct bio *bio)
}
EXPORT_SYMBOL_GPL(__bio_integrity_action);

void bio_integrity_alloc_buf(struct bio *bio, bool zero_buffer)
void bio_integrity_alloc_buf(struct bio *bio, gfp_t gfp, bool zero_buffer)
{
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
struct bio_integrity_payload *bip = bio_integrity(bio);
unsigned int len = bio_integrity_bytes(bi, bio_sectors(bio));
gfp_t gfp = GFP_NOIO | (zero_buffer ? __GFP_ZERO : 0);
void *buf;

buf = kmalloc(len, (gfp & ~__GFP_DIRECT_RECLAIM) |
__GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN);
buf = kmalloc(len, gfp | __GFP_NOWARN | (zero_buffer ? __GFP_ZERO : 0));
if (unlikely(!buf)) {
struct page *page;

page = mempool_alloc(&integrity_buf_pool, GFP_NOFS);
page = mempool_alloc(&integrity_buf_pool, gfp);
if (zero_buffer)
memset(page_address(page), 0, len);
bvec_set_page(&bip->bip_vec[0], page, len, 0);
Expand Down
21 changes: 18 additions & 3 deletions block/bio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1321,6 +1321,7 @@ static int bio_iov_iter_bounce_write(struct bio *bio, struct iov_iter *iter,

do {
size_t this_len = min(total_len, SZ_1M);
size_t copied;
struct folio *folio;

if (this_len > minsize * 2)
Expand All @@ -1334,12 +1335,26 @@ static int bio_iov_iter_bounce_write(struct bio *bio, struct iov_iter *iter,
break;
bio_add_folio_nofail(bio, folio, this_len, 0);

if (copy_from_iter(folio_address(folio), this_len, iter) !=
this_len) {
if (iter->nofault)
copied = copy_folio_from_iter_atomic(folio, 0, this_len,
iter);
else
copied = copy_folio_from_iter(folio, 0, this_len, iter);
if (copied < this_len) {
/*
* Need to revert the iov iter for all bytes we have
* copied.
*
* However the bio size differs from the real copied
* bytes as @this_len is queued but only advanced
* less than that.
* Need to compensate that for the revert.
*/
iov_iter_revert(iter, bio->bi_iter.bi_size - this_len +
copied);
bio_free_folios(bio);
return -EFAULT;
}

total_len -= this_len;
} while (total_len && bio->bi_vcnt < bio->bi_max_vecs);

Expand Down
15 changes: 9 additions & 6 deletions block/blk-cgroup-rwstat.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,24 +101,27 @@ void blkg_rwstat_recursive_sum(struct blkcg_gq *blkg, struct blkcg_policy *pol,
struct cgroup_subsys_state *pos_css;
unsigned int i;

lockdep_assert_held(&blkg->q->queue_lock);
WARN_ON_ONCE(!rcu_read_lock_held());

memset(sum, 0, sizeof(*sum));
rcu_read_lock();
blkg_for_each_descendant_pre(pos_blkg, pos_css, blkg) {
struct blkg_rwstat *rwstat;

if (!pos_blkg->online)
continue;

if (pol)
rwstat = (void *)blkg_to_pd(pos_blkg, pol) + off;
else
if (pol) {
struct blkg_policy_data *pd = blkg_to_pd(pos_blkg, pol);

if (!pd)
continue;
rwstat = (void *)pd + off;
} else {
rwstat = (void *)pos_blkg + off;
}

for (i = 0; i < BLKG_RWSTAT_NR; i++)
sum->cnt[i] += blkg_rwstat_read_counter(rwstat, i);
}
rcu_read_unlock();
}
EXPORT_SYMBOL_GPL(blkg_rwstat_recursive_sum);
Loading
Loading