[Devel] [PATCH RH8 09/61] ploop: Convert read and write cluster sync
Kirill Tkhai
ktkhai at virtuozzo.com
Fri May 14 18:55:24 MSK 2021
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
drivers/md/dm-ploop-cmd.c | 110 +++++++++++++++++++++++++++++----------------
drivers/md/dm-ploop.h | 9 ++--
2 files changed, 76 insertions(+), 43 deletions(-)
diff --git a/drivers/md/dm-ploop-cmd.c b/drivers/md/dm-ploop-cmd.c
index 9fd2b8664edc..d49d346b9de8 100644
--- a/drivers/md/dm-ploop-cmd.c
+++ b/drivers/md/dm-ploop-cmd.c
@@ -7,6 +7,44 @@
#define DM_MSG_PREFIX "ploop"
+static void free_pvec_with_pages(struct ploop_bvec *pvec)
+{
+ if (pvec) {
+ while (pvec->nr_pages-- > 0)
+ put_page(pvec->bvec[pvec->nr_pages].bv_page);
+ kfree(pvec);
+ }
+}
+
+static struct ploop_bvec *alloc_pvec_with_pages(ushort nr_pages)
+{
+ struct ploop_bvec *pvec;
+ struct bio_vec *bvec;
+ u32 size;
+ int i;
+
+ size = sizeof(struct ploop_bvec) + nr_pages * sizeof(struct bio_vec);
+ pvec = kzalloc(size, GFP_NOIO);
+ if (!pvec)
+ return NULL;
+ pvec->nr_pages = nr_pages;
+
+ bvec = pvec->bvec;
+ for (i = 0; i < nr_pages; i++) {
+ bvec[i].bv_page = alloc_page(GFP_NOIO);
+ if (!bvec[i].bv_page)
+ goto err;
+ bvec[i].bv_len = PAGE_SIZE;
+ bvec[i].bv_offset = 0;
+ }
+
+ return pvec;
+err:
+ pvec->nr_pages = i;
+ free_pvec_with_pages(pvec);
+ return NULL;
+}
+
static void ploop_queue_deferred_cmd(struct ploop *ploop, struct ploop_cmd *cmd)
{
unsigned long flags;
@@ -175,61 +213,54 @@ void bio_prepare_offsets(struct ploop *ploop, struct bio *bio,
bio->bi_iter.bi_size = 1 << (cluster_log + 9);
}
-int ploop_read_cluster_sync(struct ploop *ploop, struct bio *bio,
- unsigned int cluster)
+static int ploop_read_cluster_sync(struct ploop *ploop, struct ploop_bvec *pvec,
+ unsigned int dst_cluster)
{
- bio_reset(bio);
- bio_prepare_offsets(ploop, bio, cluster);
- remap_to_origin(ploop, bio);
- bio_set_op_attrs(bio, REQ_OP_READ, 0);
+ u64 page_id = to_bytes((u64)dst_cluster << ploop->cluster_log) >> PAGE_SHIFT;
- return submit_bio_wait(bio);
+ return rw_pages_sync(READ, top_delta(ploop)->file, page_id, pvec);
}
-static int ploop_write_cluster_sync(struct ploop *ploop, struct bio *bio,
- unsigned int cluster)
+static int ploop_write_cluster_sync(struct ploop *ploop, struct ploop_bvec *pvec,
+ unsigned int dst_cluster)
{
- struct block_device *bdev = ploop->origin_dev->bdev;
+ u64 page_id = to_bytes((u64)dst_cluster << ploop->cluster_log) >> PAGE_SHIFT;
+ struct file *file = top_delta(ploop)->file;
int ret;
- bio_reset(bio);
- bio_prepare_offsets(ploop, bio, cluster);
- remap_to_origin(ploop, bio);
- bio_set_op_attrs(bio, REQ_OP_WRITE, REQ_FUA | REQ_PREFLUSH);
-
- ret = submit_bio_wait(bio);
+ ret = vfs_fsync(file, 0);
if (ret)
return ret;
- if (!blk_queue_fua(bdev_get_queue(bdev))) {
- /*
- * Error here does not mean that cluster write is failed,
- * since ploop_map() could submit more bios in parallel.
- * But it's not possible to differ them. Should we block
- * ploop_map() during we do this?
- */
- ret = blkdev_issue_flush(bdev, GFP_NOIO, NULL);
- }
+ ret = rw_pages_sync(WRITE, file, page_id, pvec);
+ if (ret)
+ return ret;
- return ret;
+ /* track_bio(ploop, bio); */
+ return vfs_fsync(file, 0);
}
static int ploop_write_zero_cluster_sync(struct ploop *ploop,
- struct bio *bio,
+ struct ploop_bvec *pvec,
unsigned int cluster)
{
- bio_reset(bio);
- bio_prepare_offsets(ploop, bio, cluster);
- zero_fill_bio(bio);
+ void *data;
+ int i;
+
+ for (i = 0; i < pvec->nr_pages; i++) {
+ data = kmap_atomic(pvec->bvec[i].bv_page);
+ memset(data, 0, PAGE_SIZE);
+ kunmap_atomic(data);
+ }
- return ploop_write_cluster_sync(ploop, bio, cluster);
+ return ploop_write_cluster_sync(ploop, pvec, cluster);
}
static int ploop_grow_relocate_cluster(struct ploop *ploop,
struct ploop_index_wb *piwb,
struct ploop_cmd *cmd)
{
- struct bio *bio = cmd->resize.bio;
+ struct ploop_bvec *pvec = cmd->resize.pvec;
unsigned int new_dst, cluster, dst_cluster;
bool is_locked;
int ret = 0;
@@ -260,7 +291,7 @@ static int ploop_grow_relocate_cluster(struct ploop *ploop,
goto out;
/* Read full cluster sync */
- ret = ploop_read_cluster_sync(ploop, bio, dst_cluster);
+ ret = ploop_read_cluster_sync(ploop, pvec, dst_cluster);
if (ret < 0)
goto out;
@@ -270,7 +301,7 @@ static int ploop_grow_relocate_cluster(struct ploop *ploop,
goto out;
/* Write cluster to new destination */
- ret = ploop_write_cluster_sync(ploop, bio, new_dst);
+ ret = ploop_write_cluster_sync(ploop, pvec, new_dst);
if (ret) {
ploop_reset_bat_update(piwb);
goto out;
@@ -296,7 +327,7 @@ static int ploop_grow_relocate_cluster(struct ploop *ploop,
cmd->resize.dst_cluster++;
/* Zero new BAT entries on disk. */
- ret = ploop_write_zero_cluster_sync(ploop, bio, dst_cluster);
+ ret = ploop_write_zero_cluster_sync(ploop, pvec, dst_cluster);
out:
return ret;
}
@@ -520,10 +551,9 @@ static int ploop_resize(struct ploop *ploop, u64 new_size)
old_size = DIV_ROUND_UP(ploop->hb_nr, 8);
memset(cmd.resize.holes_bitmap + old_size, 0xff, size - old_size);
- cmd.resize.bio = alloc_bio_with_pages(ploop);
- if (!cmd.resize.bio)
+ cmd.resize.pvec = alloc_pvec_with_pages(to_bytes(1 << cluster_log));
+ if (!cmd.resize.pvec)
goto err;
- cmd.resize.bio->bi_status = 0;
cmd.resize.cluster = UINT_MAX;
cmd.resize.dst_cluster = nr_old_bat_clusters;
@@ -543,8 +573,8 @@ static int ploop_resize(struct ploop *ploop, u64 new_size)
ret = cmd.retval;
err:
- if (cmd.resize.bio)
- free_bio_with_pages(ploop, cmd.resize.bio);
+ if (cmd.resize.pvec)
+ free_pvec_with_pages(cmd.resize.pvec);
kvfree(cmd.resize.holes_bitmap);
free_md_pages_tree(&cmd.resize.md_pages_root);
return ret;
diff --git a/drivers/md/dm-ploop.h b/drivers/md/dm-ploop.h
index 55a30722b18b..63a860bc84c8 100644
--- a/drivers/md/dm-ploop.h
+++ b/drivers/md/dm-ploop.h
@@ -65,7 +65,7 @@ struct ploop_cmd {
unsigned int end_dst_cluster;
unsigned int nr_old_bat_clu;
unsigned int cluster, dst_cluster;
- struct bio *bio;
+ struct ploop_bvec *pvec;
} resize;
struct {
#define NR_MERGE_BIOS 64
@@ -278,6 +278,11 @@ struct ploop_cow {
void *data; /* Second argument of end_fn */
};
+struct ploop_bvec {
+ unsigned int nr_pages;
+ struct bio_vec bvec[0];
+};
+
extern bool ignore_signature_disk_in_use;
extern struct kmem_cache *piocb_cache;
extern struct kmem_cache *cow_cache;
@@ -522,8 +527,6 @@ extern void bio_prepare_offsets(struct ploop *, struct bio *, unsigned int);
extern void ploop_free_pb(struct push_backup *pb);
extern void cleanup_backup(struct ploop *ploop);
-extern int ploop_read_cluster_sync(struct ploop *, struct bio *, unsigned int);
-
extern int ploop_setup_metadata(struct ploop *ploop, struct page *page);
extern int ploop_read_delta_metadata(struct ploop *ploop, struct file *file,
void **d_hdr);
More information about the Devel
mailing list