Commit b6207430 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jens Axboe
Browse files

block: never take page references for ITER_BVEC



If we pass pages through an iov_iter we always already have a reference
in the caller.  Thus remove the ITER_BVEC_FLAG_NO_REF and don't take
reference to pages by default for bvec backed iov_iters.

Reviewed-by: default avatarMinwoo Im <minwoo.im.dev@gmail.com>
Reviewed-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent d7c8aa85
Loading
Loading
Loading
Loading
+1 −13
Original line number Diff line number Diff line
@@ -836,15 +836,6 @@ int bio_add_page(struct bio *bio, struct page *page,
}
EXPORT_SYMBOL(bio_add_page);

static void bio_get_pages(struct bio *bio)
{
	struct bvec_iter_all iter_all;
	struct bio_vec *bvec;

	bio_for_each_segment_all(bvec, bio, iter_all)
		get_page(bvec->bv_page);
}

void bio_release_pages(struct bio *bio, bool mark_dirty)
{
	struct bvec_iter_all iter_all;
@@ -960,11 +951,8 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
			ret = __bio_iov_iter_get_pages(bio, iter);
	} while (!ret && iov_iter_count(iter) && !bio_full(bio));

	if (iov_iter_bvec_no_ref(iter))
	if (is_bvec)
		bio_set_flag(bio, BIO_NO_PAGE_REF);
	else if (is_bvec)
		bio_get_pages(bio);

	return bio->bi_vcnt ? 0 : ret;
}

+4 −12
Original line number Diff line number Diff line
@@ -264,20 +264,12 @@ lo_do_transfer(struct loop_device *lo, int cmd,
	return ret;
}

static inline void loop_iov_iter_bvec(struct iov_iter *i,
		unsigned int direction, const struct bio_vec *bvec,
		unsigned long nr_segs, size_t count)
{
	iov_iter_bvec(i, direction, bvec, nr_segs, count);
	i->type |= ITER_BVEC_FLAG_NO_REF;
}

static int lo_write_bvec(struct file *file, struct bio_vec *bvec, loff_t *ppos)
{
	struct iov_iter i;
	ssize_t bw;

	loop_iov_iter_bvec(&i, WRITE, bvec, 1, bvec->bv_len);
	iov_iter_bvec(&i, WRITE, bvec, 1, bvec->bv_len);

	file_start_write(file);
	bw = vfs_iter_write(file, &i, ppos, 0);
@@ -355,7 +347,7 @@ static int lo_read_simple(struct loop_device *lo, struct request *rq,
	ssize_t len;

	rq_for_each_segment(bvec, rq, iter) {
		loop_iov_iter_bvec(&i, READ, &bvec, 1, bvec.bv_len);
		iov_iter_bvec(&i, READ, &bvec, 1, bvec.bv_len);
		len = vfs_iter_read(lo->lo_backing_file, &i, &pos, 0);
		if (len < 0)
			return len;
@@ -396,7 +388,7 @@ static int lo_read_transfer(struct loop_device *lo, struct request *rq,
		b.bv_offset = 0;
		b.bv_len = bvec.bv_len;

		loop_iov_iter_bvec(&i, READ, &b, 1, b.bv_len);
		iov_iter_bvec(&i, READ, &b, 1, b.bv_len);
		len = vfs_iter_read(lo->lo_backing_file, &i, &pos, 0);
		if (len < 0) {
			ret = len;
@@ -563,7 +555,7 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd,
	}
	atomic_set(&cmd->ref, 2);

	loop_iov_iter_bvec(&iter, rw, bvec, nr_bvec, blk_rq_bytes(rq));
	iov_iter_bvec(&iter, rw, bvec, nr_bvec, blk_rq_bytes(rq));
	iter.iov_offset = offset;

	cmd->iocb.ki_pos = pos;
+0 −3
Original line number Diff line number Diff line
@@ -997,9 +997,6 @@ static int io_import_fixed(struct io_ring_ctx *ctx, int rw,
	iov_iter_bvec(iter, rw, imu->bvec, imu->nr_bvecs, offset + len);
	if (offset)
		iov_iter_advance(iter, offset);

	/* don't drop a reference to these pages */
	iter->type |= ITER_BVEC_FLAG_NO_REF;
	return 0;
}

+1 −9
Original line number Diff line number Diff line
@@ -19,9 +19,6 @@ struct kvec {
};

enum iter_type {
	/* set if ITER_BVEC doesn't hold a bv_page ref */
	ITER_BVEC_FLAG_NO_REF = 2,

	/* iter types */
	ITER_IOVEC = 4,
	ITER_KVEC = 8,
@@ -56,7 +53,7 @@ struct iov_iter {

static inline enum iter_type iov_iter_type(const struct iov_iter *i)
{
	return i->type & ~(READ | WRITE | ITER_BVEC_FLAG_NO_REF);
	return i->type & ~(READ | WRITE);
}

static inline bool iter_is_iovec(const struct iov_iter *i)
@@ -89,11 +86,6 @@ static inline unsigned char iov_iter_rw(const struct iov_iter *i)
	return i->type & (READ | WRITE);
}

static inline bool iov_iter_bvec_no_ref(const struct iov_iter *i)
{
	return (i->type & ITER_BVEC_FLAG_NO_REF) != 0;
}

/*
 * Total number of bytes covered by an iovec.
 *