[1/6] ploop: Remove obsolete ioctls

Submitted by Kirill Tkhai on April 30, 2019, 10:03 a.m.

Details

Message ID 155661860954.22929.9698864982122565692.stgit@localhost.localdomain
State New
Series "ploop: Remove maintaince-mode-driven discard ioctls and leftovers"
Headers show

Commit Message

Kirill Tkhai April 30, 2019, 10:03 a.m.
These ioctls are already disabled, and the patch
just kills unused code and dependences.

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 drivers/block/ploop/Makefile   |    2 
 drivers/block/ploop/dev.c      |  830 +-----------------------------
 drivers/block/ploop/discard.c  |  121 ----
 drivers/block/ploop/discard.h  |   15 -
 drivers/block/ploop/freeblks.c | 1110 ----------------------------------------
 drivers/block/ploop/freeblks.h |   58 --
 include/linux/ploop/ploop.h    |   19 -
 include/linux/ploop/ploop_if.h |   20 -
 8 files changed, 45 insertions(+), 2130 deletions(-)
 delete mode 100644 drivers/block/ploop/discard.c
 delete mode 100644 drivers/block/ploop/discard.h
 delete mode 100644 drivers/block/ploop/freeblks.c
 delete mode 100644 drivers/block/ploop/freeblks.h

Patch hide | download patch | download mbox

diff --git a/drivers/block/ploop/Makefile b/drivers/block/ploop/Makefile
index e572dd54a9b5..7741ec584164 100644
--- a/drivers/block/ploop/Makefile
+++ b/drivers/block/ploop/Makefile
@@ -8,7 +8,7 @@  CFLAGS_io_direct.o = -I$(src)
 CFLAGS_ploop_events.o = -I$(src)
 
 obj-$(CONFIG_BLK_DEV_PLOOP)	+= ploop.o
-ploop-objs := dev.o map.o io.o sysfs.o tracker.o freeblks.o ploop_events.o discard.o push_backup.o
+ploop-objs := dev.o map.o io.o sysfs.o tracker.o ploop_events.o push_backup.o
 
 obj-$(CONFIG_BLK_DEV_PLOOP)	+= pfmt_ploop1.o
 pfmt_ploop1-objs := fmt_ploop1.o
diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c
index ca7bd0bbf5b7..27f4a5b24410 100644
--- a/drivers/block/ploop/dev.c
+++ b/drivers/block/ploop/dev.c
@@ -25,8 +25,6 @@ 
 #include <bc/beancounter.h>
 #include <linux/ploop/ploop.h>
 #include "ploop_events.h"
-#include "freeblks.h"
-#include "discard.h"
 #include "push_backup.h"
 
 /* Structures and terms:
@@ -528,42 +526,7 @@  ploop_bio_queue(struct ploop_device * plo, struct bio * bio,
 	    ploop_pb_check_and_clear_bit(plo->pbd, preq->req_cluster))
 		ploop_set_blockable(plo, preq);
 
-	if (test_bit(PLOOP_S_DISCARD, &plo->state) &&
-	    unlikely(bio->bi_rw & REQ_DISCARD)) {
-		int clu_size = cluster_size_in_sec(plo);
-		int i = (clu_size - 1) & bio->bi_sector;
-		int err = 0;
-
-		if (i) {
-			preq->req_cluster++;
-			if (preq->req_size >= clu_size)
-				preq->req_size -= clu_size - i;
-		}
-
-		if (preq->req_size < clu_size ||
-		    (err = ploop_discard_add_bio(plo->fbd, bio))) {
-			if (test_bit(BIO_BDEV_REUSED, &bio->bi_flags)) {
-				struct io_context *ioc;
-				ioc = (struct io_context *)(bio->bi_bdev);
-				atomic_dec(&ioc->nr_tasks);
-				put_io_context_active(ioc);
-
-				bio->bi_bdev = plo->bdev;
-				clear_bit(BIO_BDEV_REUSED, &bio->bi_flags);
-			}
-			BIO_ENDIO(plo->queue, bio, err);
-			list_add(&preq->list, &plo->free_list);
-			plo->free_qlen++;
-			plo->bio_discard_qlen--;
-			plo->bio_total--;
-			return;
-		}
-
-		preq->state = (1 << PLOOP_REQ_SYNC) | (1 << PLOOP_REQ_DISCARD);
-		preq->dst_iblock = 0;
-		preq->bl.head = preq->bl.tail = NULL;
-	} else
-		preq->bl.head = preq->bl.tail = bio;
+	preq->bl.head = preq->bl.tail = bio;
 
 	if (test_bit(BIO_BDEV_REUSED, &bio->bi_flags)) {
 		    preq->ioc = (struct io_context *)(bio->bi_bdev);
@@ -823,15 +786,9 @@  static void ploop_unplug(struct blk_plug_cb *cb, bool from_schedule)
 static void
 process_discard_bio_queue(struct ploop_device * plo, struct list_head *drop_list)
 {
-	bool discard = test_bit(PLOOP_S_DISCARD, &plo->state);
-
 	while (!list_empty(&plo->free_list)) {
 		struct bio *tmp;
 
-		/* Only one discard bio can be handled concurrently */
-		if (discard && ploop_discard_is_inprogress(plo->fbd))
-			return;
-
 		tmp = bio_list_pop(&plo->bio_discard_list);
 		if (tmp == NULL)
 			break;
@@ -1316,22 +1273,6 @@  static void del_pb_lockout(struct ploop_request *preq)
 	__del_lockout(preq, true);
 }
 
-static void ploop_discard_wakeup(struct ploop_request *preq, int err)
-{
-	struct ploop_device *plo = preq->plo;
-
-	if (err || !ploop_fb_get_n_free(plo->fbd)) {
-		/* Only one discard request is processed */
-		ploop_fb_reinit(plo->fbd, err);
-	} else
-		set_bit(PLOOP_S_DISCARD_LOADED, &plo->state);
-
-	if (atomic_dec_and_test(&plo->maintenance_cnt))
-		if (test_bit(PLOOP_S_DISCARD_LOADED, &plo->state) ||
-		    !test_bit(PLOOP_S_DISCARD, &plo->state))
-			complete(&plo->maintenance_comp);
-}
-
 static void ploop_complete_request(struct ploop_request * preq)
 {
 	struct ploop_device * plo = preq->plo;
@@ -1393,8 +1334,7 @@  static void ploop_complete_request(struct ploop_request * preq)
 
 		if (atomic_dec_and_test(&plo->maintenance_cnt))
 			complete(&plo->maintenance_comp);
-	} else if (test_bit(PLOOP_REQ_DISCARD, &preq->state))
-		ploop_discard_wakeup(preq, preq->error);
+	}
 
 	if (preq->aux_bio) {
 		int i;
@@ -1438,19 +1378,15 @@  static void ploop_complete_request(struct ploop_request * preq)
 
 	plo->active_reqs--;
 
-	if (unlikely(test_bit(PLOOP_REQ_ZERO, &preq->state))) {
-		ploop_fb_put_zero_request(plo->fbd, preq);
-	} else {
-		ploop_uncongest(plo);
-		list_add(&preq->list, &plo->free_list);
-		plo->free_qlen++;
-		if (waitqueue_active(&plo->req_waitq))
-			wake_up(&plo->req_waitq);
-		else if (waitqueue_active(&plo->waitq) &&
-			 (plo->bio_head ||
-			  !bio_list_empty(&plo->bio_discard_list)))
-			wake_up_interruptible(&plo->waitq);
-	}
+	ploop_uncongest(plo);
+	list_add(&preq->list, &plo->free_list);
+	plo->free_qlen++;
+	if (waitqueue_active(&plo->req_waitq))
+		wake_up(&plo->req_waitq);
+	else if (waitqueue_active(&plo->waitq) &&
+		 (plo->bio_head ||
+		  !bio_list_empty(&plo->bio_discard_list)))
+		wake_up_interruptible(&plo->waitq);
 	plo->bio_total -= nr_completed;
 
 	if (plo->tune.congestion_detection &&
@@ -1670,44 +1606,6 @@  static int prepare_merge_req(struct ploop_request * preq)
 	return 1;
 }
 
-void ploop_queue_zero_request(struct ploop_device *plo,
-			      struct ploop_request *orig_preq, cluster_t clu)
-{
-	struct ploop_request * preq;
-
-	spin_lock_irq(&plo->lock);
-
-	preq = ploop_fb_get_zero_request(plo->fbd);
-	preq->bl.tail = preq->bl.head = NULL;
-	preq->req_cluster = clu;
-	preq->req_size = 0;
-	preq->req_rw = WRITE_SYNC;
-	preq->eng_state = PLOOP_E_ENTRY;
-	preq->state = (1 << PLOOP_REQ_ZERO);
-	if (test_bit(PLOOP_REQ_SYNC, &orig_preq->state))
-		preq->state |= (1 << PLOOP_REQ_SYNC);
-	preq->error = 0;
-	preq->tstamp = jiffies;
-	preq->iblock = 0;
-	preq->preq_ub = get_beancounter(get_exec_ub());
-
-	if (test_bit(PLOOP_REQ_RELOC_S, &orig_preq->state)) {
-		if (orig_preq->dst_iblock == ~0U)
-			orig_preq->eng_state = PLOOP_E_RELOC_COMPLETE;
-	} else {
-		orig_preq->eng_state = orig_preq->iblock ?
-			PLOOP_E_DELTA_ZERO_INDEX : PLOOP_E_ZERO_INDEX;
-	}
-	orig_preq->iblock = 0;
-	INIT_LIST_HEAD(&preq->delay_list);
-	list_add_tail(&orig_preq->list, &preq->delay_list);
-
-	list_add(&preq->list, &plo->ready_queue);
-	plo->active_reqs++;
-
-	spin_unlock_irq(&plo->lock);
-}
-
 static void
 ploop_reloc_sched_read(struct ploop_request *preq, iblock_t iblk)
 {
@@ -1741,100 +1639,6 @@  ploop_reloc_sched_read(struct ploop_request *preq, iblock_t iblk)
 			      &sbl, iblk, cluster_size_in_sec(plo));
 }
 
-/*
- * Returns 0 if and only if a free block was successfully reused
- */
-static int
-ploop_reuse_free_block(struct ploop_request *preq)
-{
-	struct ploop_device *plo       = preq->plo;
-	struct ploop_delta  *top_delta = ploop_top_delta(plo);
-	iblock_t  iblk;
-	cluster_t clu;
-	int	  rc;
-	unsigned long pin_state;
-
-	if (plo->maintenance_type != PLOOP_MNTN_FBLOADED &&
-	    plo->maintenance_type != PLOOP_MNTN_RELOC)
-		return -1;
-
-	rc = ploop_fb_get_free_block(plo->fbd, &clu, &iblk);
-
-	/* simple case - no free blocks left */
-	if (rc < 0)
-		return rc;
-
-	/* a free block to reuse requires zeroing index */
-	if (rc > 0) {
-		ploop_queue_zero_request(plo, preq, clu);
-		return 0;
-	}
-
-	/* 'rc == 0' - use iblk as a lost block */
-	pin_state = preq->iblock ? PLOOP_E_DELTA_ZERO_INDEX :
-				   PLOOP_E_ZERO_INDEX;
-	preq->iblock = iblk;
-
-	/* pin preq to some reloc request processing iblk ? */
-	if (ploop_fb_check_reloc_req(plo->fbd, preq, pin_state))
-		return 0;
-
-	/* iblk is a lost block and nobody is relocating it now */
-	preq->eng_state = PLOOP_E_DATA_WBI;
-	__TRACE("T2 %p %u\n", preq, preq->req_cluster);
-	plo->st.bio_out++;
-
-	if (pin_state == PLOOP_E_ZERO_INDEX) {
-		top_delta->io.ops->submit(&top_delta->io, preq, preq->req_rw,
-					  &preq->bl, preq->iblock,
-					  preq->req_size);
-	} else { /* PLOOP_E_DELTA_READ */
-		struct bio_list sbl;
-
-		BUG_ON (preq->aux_bio == NULL);
-		sbl.head = sbl.tail = preq->aux_bio;
-
-		top_delta->io.ops->submit(&top_delta->io, preq, preq->req_rw,
-				      &sbl, preq->iblock, cluster_size_in_sec(plo));
-	}
-
-	return 0;
-}
-
-/*
- * Returns 0 if and only if zero preq was successfully processed
- */
-static int
-ploop_entry_zero_req(struct ploop_request *preq)
-{
-	struct ploop_device *plo       = preq->plo;
-	struct ploop_delta  *top_delta = ploop_top_delta(plo);
-	int	 level;
-	iblock_t iblk = 0;
-	int	 err;
-
-	err = ploop_find_map(&plo->map, preq);
-	if (err) {
-		if (err == 1) {
-			__TRACE("m %p %u\n", preq, *clu);
-			return 0;
-		}
-		return err;
-	}
-
-	level = map_get_index(preq, preq->req_cluster, &iblk);
-	if (level != top_delta->level) {
-		printk("Can't zero index on wrong level=%d "
-		       "(top_level=%d req_cluster=%u iblk=%u/%u)\n",
-		       level, top_delta->level, preq->req_cluster,
-		       iblk, preq->iblock);
-		return -EIO;
-	}
-
-	ploop_index_update(preq);
-	return 0;
-}
-
 #define MAP_MAX_IND(preq) min(map_get_mn_end(preq->map),	\
 			      preq->plo->map.max_index - 1)
 
@@ -1895,96 +1699,12 @@  ploop_entry_reloc_a_req(struct ploop_request *preq, iblock_t *iblk)
 	return 0;
 }
 
-/*
- * Returns 0 if and only if RELOC_S preq was successfully processed.
- *
- * Sets preq->req_cluster to the block we're going to relocate.
- * Returning 0, always set *iblk to a meaningful value: either
- * zero (if no more blocks to relocate or block to relocate is free
- *	 (and zero-index op is scheduled) or map is being read)
- * or iblock that preq->req_cluster points to.
- */
-static int
-ploop_entry_reloc_s_req(struct ploop_request *preq, iblock_t *iblk)
-{
-	struct ploop_device *plo       = preq->plo;
-	struct ploop_delta  *top_delta = ploop_top_delta(plo);
-
-	cluster_t from_clu, to_clu;
-	iblock_t from_iblk, to_iblk;
-	u32 free;
-	int level;
-	int err;
-
-	*iblk = 0;
-
-	if (preq->req_cluster == ~0U) {
-		cluster_t zero_cluster;
-
-		BUG_ON (preq->error);
-		err = ploop_fb_get_reloc_block(plo->fbd, &from_clu, &from_iblk,
-					       &to_clu, &to_iblk, &free);
-		if (err < 0) {
-			preq->eng_state = PLOOP_E_COMPLETE;
-			ploop_complete_request(preq);
-			return 0;
-		}
-
-		preq->req_cluster = from_clu;
-		preq->src_iblock  = from_iblk;
-		ploop_fb_add_reloc_req(plo->fbd, preq);
-
-		if (free) {
-			preq->dst_iblock  = ~0U;
-			preq->dst_cluster = ~0U;
-			zero_cluster = preq->req_cluster;
-		} else {
-			preq->dst_iblock  = to_iblk;
-			preq->dst_cluster = to_clu;
-			zero_cluster = preq->dst_cluster;
-		}
-
-		ploop_queue_zero_request(plo, preq, zero_cluster);
-		return 0;
-	}
-
-	err = ploop_find_map(&plo->map, preq);
-	if (err) {
-		if (err == 1) {
-			__TRACE("m %p %u\n", preq, *clu);
-			return 0;
-		}
-		return err;
-	}
-	BUG_ON (preq->map == NULL);
-
-	level = map_get_index(preq, preq->req_cluster, iblk);
-	if (level != top_delta->level) {
-		printk("Can't relocate block on wrong level=%d "
-		       "(top_level=%d req_cluster=%u iblk=%u/%u)\n",
-		       level, top_delta->level, preq->req_cluster,
-		       *iblk, preq->iblock);
-		return -EIO;
-	}
-	if (preq->src_iblock != *iblk) {
-		printk("Can't relocate block due to wrong mapping: "
-		       "req_cluster=%u should point to iblk=%u while "
-		       "map_get_index() calculated iblk=%u\n",
-		       preq->req_cluster, preq->src_iblock, *iblk);
-		return -EIO;
-	}
-
-	return 0;
-}
-
 /* dummy wrapper around ploop_entry_reloc_[a|s]_req() */
 static int
 ploop_entry_reloc_req(struct ploop_request *preq, iblock_t *iblk)
 {
 	if (test_bit(PLOOP_REQ_RELOC_A, &preq->state))
 		return ploop_entry_reloc_a_req(preq, iblk);
-	else if (test_bit(PLOOP_REQ_RELOC_S, &preq->state))
-		return ploop_entry_reloc_s_req(preq, iblk);
 	else
 		BUG();
 }
@@ -2046,106 +1766,6 @@  ploop_entry_nullify_req(struct ploop_request *preq)
 	return 0;
 }
 
-static int discard_get_index(struct ploop_request *preq)
-{
-	struct ploop_device *plo       = preq->plo;
-	struct ploop_delta  *top_delta = ploop_top_delta(plo);
-	int	 level;
-	int	 err;
-
-	preq->iblock = 0;
-
-	err = ploop_find_map(&plo->map, preq);
-	if (err)
-		return err;
-
-	level = map_get_index(preq, preq->req_cluster, &preq->iblock);
-	if (level != top_delta->level)
-		preq->iblock = 0;
-
-	if (preq->map) {
-		spin_lock_irq(&plo->lock);
-		map_release(preq->map);
-		preq->map = NULL;
-		spin_unlock_irq(&plo->lock);
-	}
-
-	return 0;
-}
-
-static int ploop_entry_discard_req(struct ploop_request *preq)
-{
-	int err = 0;
-	struct ploop_device * plo = preq->plo;
-	unsigned int len = 0;
-	cluster_t last_clu;
-
-	if (!test_bit(PLOOP_S_DISCARD, &plo->state)) {
-		err = -EOPNOTSUPP;
-		goto err;
-	}
-
-	BUG_ON(plo->maintenance_type != PLOOP_MNTN_DISCARD);
-
-	last_clu = (preq->req_sector + preq->req_size) >> plo->cluster_log;
-
-	for (; preq->req_cluster < last_clu; preq->req_cluster++) {
-		len = preq->req_cluster - preq->dst_cluster;
-
-		err = discard_get_index(preq);
-		if (err) {
-			if (err == 1)
-				return 0;
-			goto err;
-		}
-
-		if (preq->dst_iblock &&
-		    (!preq->iblock || preq->dst_iblock + len != preq->iblock)) {
-			err = ploop_fb_add_free_extent(plo->fbd,
-							preq->dst_cluster,
-							preq->dst_iblock, len);
-			preq->dst_iblock = 0;
-			if (err) {
-				if (err == -EINVAL) {
-					printk("ploop_entry_discard_req1: "
-					       "(%lu %u; %u %u; %u %u)\n",
-					       preq->req_sector, preq->req_size,
-					       preq->req_cluster, preq->iblock,
-					       preq->dst_cluster, preq->dst_iblock);
-					WARN_ONCE(1, "add_free_extent failed\n");
-				}
-				goto err;
-			}
-		}
-
-		if (!preq->dst_iblock && preq->iblock) {
-			preq->dst_cluster = preq->req_cluster;
-			preq->dst_iblock = preq->iblock;
-		}
-	}
-
-	if (preq->dst_iblock) {
-		len = preq->req_cluster - preq->dst_cluster;
-		err = ploop_fb_add_free_extent(plo->fbd, preq->dst_cluster,
-						preq->dst_iblock, len);
-		if (err == -EINVAL) {
-			printk("ploop_entry_discard_req2: "
-			       "(%lu %u; %u %u; %u %u)\n",
-			       preq->req_sector, preq->req_size,
-			       preq->req_cluster, preq->iblock,
-			       preq->dst_cluster, preq->dst_iblock);
-			WARN_ONCE(1, "add_free_extent failed\n");
-		}
-	}
-
-err:
-	preq->error = err;
-	preq->eng_state = PLOOP_E_COMPLETE;
-	ploop_complete_request(preq);
-
-	return 0;
-}
-
 /* Main preq state machine */
 
 static inline bool preq_is_special(struct ploop_request * preq)
@@ -2257,17 +1877,7 @@  ploop_entry_request(struct ploop_request * preq)
 		preq->req_rw |= REQ_SYNC;
 
 restart:
-	if (test_bit(PLOOP_REQ_DISCARD, &preq->state)) {
-		err = ploop_entry_discard_req(preq);
-		if (err)
-			goto error;
-		return;
-	} else if (test_bit(PLOOP_REQ_ZERO, &preq->state)) {
-		err = ploop_entry_zero_req(preq);
-		if (err)
-			goto error;
-		return;
-	} else if (test_bit(PLOOP_REQ_RELOC_A, &preq->state) ||
+	if (test_bit(PLOOP_REQ_RELOC_A, &preq->state) ||
 		   test_bit(PLOOP_REQ_RELOC_S, &preq->state)) {
 		err = ploop_entry_reloc_req(preq, &iblk);
 		if (err)
@@ -2489,10 +2099,9 @@  ploop_entry_request(struct ploop_request * preq)
 				ploop_add_lockout(preq, 0);
 				spin_unlock_irq(&plo->lock);
 
-				if (likely(ploop_reuse_free_block(preq)))
-					top_delta->ops->allocate(top_delta,
-								 preq, &preq->bl,
-								 preq->req_size);
+				top_delta->ops->allocate(top_delta,
+							 preq, &preq->bl,
+							 preq->req_size);
 			} else {
 				struct bio_list sbl;
 
@@ -2552,13 +2161,11 @@  ploop_entry_request(struct ploop_request * preq)
 			spin_unlock_irq(&plo->lock);
 
 			/* Block does not exist. */
-			if (likely(ploop_reuse_free_block(preq))) {
-				__TRACE("K %p %u\n", preq, preq->req_cluster);
-				plo->st.bio_alloc++;
-				top_delta->ops->allocate(top_delta, preq,
-							 &preq->bl,
-							 preq->req_size);
-			}
+			__TRACE("K %p %u\n", preq, preq->req_cluster);
+			plo->st.bio_alloc++;
+			top_delta->ops->allocate(top_delta, preq,
+						 &preq->bl,
+						 preq->req_size);
 		}
 	}
 	return;
@@ -2651,8 +2258,6 @@  static void ploop_req_state_process(struct ploop_request * preq)
 	case PLOOP_E_RELOC_COMPLETE:
 		BUG_ON (!test_bit(PLOOP_REQ_RELOC_S, &preq->state));
 		if (!preq->error) {
-			ploop_fb_relocate_req_completed(plo->fbd);
-			ploop_fb_del_reloc_req(plo->fbd, preq);
 			spin_lock_irq(&plo->lock);
 			if (!list_empty(&preq->delay_list)) {
 				struct ploop_request *pr;
@@ -2678,7 +2283,6 @@  static void ploop_req_state_process(struct ploop_request * preq)
 			       preq->error, preq->req_cluster, preq->iblock,
 			       preq->src_iblock, preq->dst_cluster,
 			       preq->dst_iblock);
-			ploop_fb_del_reloc_req(plo->fbd, preq);
 		}
 
 		if (!preq->error &&
@@ -2728,13 +2332,11 @@  static void ploop_req_state_process(struct ploop_request * preq)
 	}
 	case PLOOP_E_DELTA_COPIED:
 	{
-		if (likely(ploop_reuse_free_block(preq))) {
-			struct bio_list sbl;
-			sbl.head = sbl.tail = preq->aux_bio;
-			top_delta = ploop_top_delta(plo);
-			top_delta->ops->allocate(top_delta, preq,
-						 &sbl, cluster_size_in_sec(plo));
-		}
+		struct bio_list sbl;
+		sbl.head = sbl.tail = preq->aux_bio;
+		top_delta = ploop_top_delta(plo);
+		top_delta->ops->allocate(top_delta, preq,
+					 &sbl, cluster_size_in_sec(plo));
 		break;
 	}
 	case PLOOP_E_ZERO_INDEX:
@@ -2949,8 +2551,7 @@  static void ploop_wait(struct ploop_device * plo, int once, struct blk_plug *plu
 			     !plo->active_reqs))
 				break;
 		} else if (plo->bio_head ||
-			   (!bio_list_empty(&plo->bio_discard_list) &&
-			    !ploop_discard_is_inprogress(plo->fbd))) {
+			   !bio_list_empty(&plo->bio_discard_list)) {
 			/* ready_queue and entry_queue are empty, but
 			 * bio list not. Obviously, we'd like to process
 			 * bio_list instead of sleeping */
@@ -4300,8 +3901,6 @@  static int ploop_clear(struct ploop_device * plo, struct block_device * bdev)
 		return -EBUSY;
 	}
 
-	clear_bit(PLOOP_S_DISCARD_LOADED, &plo->state);
-	clear_bit(PLOOP_S_DISCARD, &plo->state);
 	clear_bit(PLOOP_S_NULLIFY, &plo->state);
 
 	destroy_deltas(plo, &plo->map);
@@ -4314,7 +3913,6 @@  static int ploop_clear(struct ploop_device * plo, struct block_device * bdev)
 		kfree(map);
 	}
 
-	ploop_fb_fini(plo->fbd, 0);
 	ploop_pb_fini(plo->pbd);
 
 	plo->maintenance_type = PLOOP_MNTN_OFF;
@@ -4557,357 +4155,6 @@  static int ploop_balloon_ioc(struct ploop_device *plo, unsigned long arg)
 	return copy_to_user((void*)arg, &ctl, sizeof(ctl));
 }
 
-static int ploop_freeblks_ioc(struct ploop_device *plo, unsigned long arg)
-{
-	struct ploop_delta *delta;
-	struct ploop_freeblks_ctl ctl;
-	struct ploop_freeblks_ctl_extent __user *extents;
-	struct ploop_freeblks_desc *fbd;
-	int i;
-	int rc = 0;
-
-	return 0;
-
-	if (list_empty(&plo->map.delta_list))
-		return -ENOENT;
-
-	if (plo->maintenance_type == PLOOP_MNTN_OFF)
-		return -EINVAL;
-	if (plo->maintenance_type != PLOOP_MNTN_BALLOON)
-		return -EBUSY;
-	BUG_ON (plo->fbd);
-
-	if (copy_from_user(&ctl, (void*)arg, sizeof(ctl)))
-		return -EFAULT;
-
-	delta = ploop_top_delta(plo);
-	if (delta->level != ctl.level) {
-		rc = -EINVAL;
-		goto exit;
-	}
-
-	fbd = ploop_fb_init(plo);
-	if (!fbd) {
-		rc = -ENOMEM;
-		goto exit;
-	}
-
-	extents = (void __user *)(arg + sizeof(ctl));
-
-	for (i = 0; i < ctl.n_extents; i++) {
-		struct ploop_freeblks_ctl_extent extent;
-
-		if (copy_from_user(&extent, &extents[i],
-					sizeof(extent))) {
-			rc = -EFAULT;
-			ploop_fb_fini(fbd, rc);
-			goto exit;
-		}
-
-		rc = ploop_fb_add_free_extent(fbd, extent.clu,
-					extent.iblk, extent.len);
-		if (rc) {
-			if (rc == -EINVAL) {
-				printk("ploop_freeblks_ioc: n=%d\n", ctl.n_extents);
-				for (i = 0; i < ctl.n_extents; i++) {
-					if (copy_from_user(&extent, &extents[i],
-							   sizeof(extent))) {
-						printk("copy failed: i=%d\n", i);
-						break;
-					}
-					printk("ploop_freeblks_ioc: i=%d: %u %u %u\n",
-					       i, extent.clu, extent.iblk, extent.len);
-				}
-				WARN_ONCE(1, "add_free_extent failed\n");
-			}
-			ploop_fb_fini(fbd, rc);
-			goto exit;
-		}
-	}
-
-	ploop_quiesce(plo);
-
-	ctl.alloc_head = delta->io.alloc_head;
-	if (copy_to_user((void*)arg, &ctl, sizeof(ctl))) {
-		rc = -EFAULT;
-		ploop_fb_fini(fbd, rc);
-	} else {
-		iblock_t a_h = delta->io.alloc_head;
-		/* make fbd visible to ploop engine */
-		plo->fbd = fbd;
-		plo->maintenance_type = PLOOP_MNTN_FBLOADED;
-		BUG_ON (a_h != ctl.alloc_head); /* quiesce sanity */
-		ploop_fb_lost_range_init(fbd, a_h);
-		ploop_fb_set_freezed_level(fbd, delta->level);
-	}
-
-	ploop_relax(plo);
-exit:
-	return rc;
-}
-
-static int ploop_fbget_ioc(struct ploop_device *plo, unsigned long arg)
-{
-	struct ploop_freeblks_ctl ctl;
-	int rc = 0;
-
-	return -EINVAL;
-
-	if (list_empty(&plo->map.delta_list))
-		return -ENOENT;
-
-	if (plo->maintenance_type == PLOOP_MNTN_DISCARD) {
-		if (!test_bit(PLOOP_S_DISCARD_LOADED, &plo->state))
-			return -EINVAL;
-	} else if (plo->maintenance_type != PLOOP_MNTN_FBLOADED)
-		return -EINVAL;
-	BUG_ON (!plo->fbd);
-
-	if (copy_from_user(&ctl, (void*)arg, sizeof(ctl)))
-		return -EFAULT;
-
-	ploop_quiesce(plo);
-	rc = ploop_fb_copy_freeblks_to_user(plo->fbd, (void*)arg, &ctl);
-	ploop_relax(plo);
-
-	return rc;
-}
-
-static int ploop_fbfilter_ioc(struct ploop_device *plo, unsigned long arg)
-{
-	int rc = 0;
-
-	return -EINVAL;
-
-	if (plo->maintenance_type != PLOOP_MNTN_DISCARD ||
-	    !test_bit(PLOOP_S_DISCARD_LOADED, &plo->state))
-		return -EINVAL;
-
-	BUG_ON (!plo->fbd);
-
-	ploop_quiesce(plo);
-	rc = ploop_fb_filter_freeblks(plo->fbd, arg);
-	ploop_relax(plo);
-
-	return rc;
-}
-
-static void ploop_relocblks_process(struct ploop_device *plo)
-{
-	int num_reqs;
-	struct ploop_request *preq;
-
-	num_reqs = plo->tune.fsync_max;
-	if (num_reqs > plo->tune.max_requests/2)
-		num_reqs = plo->tune.max_requests/2;
-	if (num_reqs < 1)
-		num_reqs = 1;
-
-	spin_lock_irq(&plo->lock);
-
-	atomic_set(&plo->maintenance_cnt, 1);
-
-	init_completion(&plo->maintenance_comp);
-
-	for (; num_reqs; num_reqs--) {
-		preq = ploop_alloc_request(plo);
-
-		preq->bl.tail = preq->bl.head = NULL;
-		preq->req_cluster = ~0U; /* uninitialized */
-		preq->req_size = 0;
-		preq->req_rw = WRITE_SYNC;
-		preq->eng_state = PLOOP_E_ENTRY;
-		preq->state = (1 << PLOOP_REQ_SYNC) | (1 << PLOOP_REQ_RELOC_S);
-		preq->error = 0;
-		preq->tstamp = jiffies;
-		preq->iblock = 0;
-		preq->prealloc_size = 0;
-		preq->preq_ub = get_beancounter(get_exec_ub());
-
-		atomic_inc(&plo->maintenance_cnt);
-
-		ploop_entry_add(plo, preq);
-
-		if (waitqueue_active(&plo->waitq))
-			wake_up_interruptible(&plo->waitq);
-	}
-
-	if (atomic_dec_and_test(&plo->maintenance_cnt))
-		complete(&plo->maintenance_comp);
-
-	spin_unlock_irq(&plo->lock);
-}
-
-static int release_fbd(struct ploop_device *plo, int err)
-{
-	clear_bit(PLOOP_S_DISCARD, &plo->state);
-
-	ploop_quiesce(plo);
-	ploop_fb_fini(plo->fbd, err);
-	plo->maintenance_type = PLOOP_MNTN_OFF;
-	ploop_relax(plo);
-
-	return err;
-}
-
-static void ploop_discard_restart(struct ploop_device *plo, int err)
-{
-	if (!err && test_bit(PLOOP_S_DISCARD, &plo->state)) {
-		ploop_fb_reinit(plo->fbd, 0);
-		atomic_set(&plo->maintenance_cnt, 0);
-		init_completion(&plo->maintenance_comp);
-		plo->maintenance_type = PLOOP_MNTN_DISCARD;
-	} else {
-		clear_bit(PLOOP_S_DISCARD, &plo->state);
-		ploop_fb_fini(plo->fbd, err);
-		plo->maintenance_type = PLOOP_MNTN_OFF;
-	}
-}
-
-static int ploop_fbdrop_ioc(struct ploop_device *plo)
-{
-	return -EINVAL;
-
-	if (list_empty(&plo->map.delta_list))
-		return -ENOENT;
-
-	if (plo->maintenance_type == PLOOP_MNTN_DISCARD) {
-		if (!test_bit(PLOOP_S_DISCARD_LOADED, &plo->state))
-			return -EINVAL;
-	} else if (plo->maintenance_type != PLOOP_MNTN_FBLOADED)
-		return -EINVAL;
-	BUG_ON (!plo->fbd);
-
-	ploop_quiesce(plo);
-	ploop_discard_restart(plo, 0);
-	ploop_relax(plo);
-
-	return 0;
-}
-
-static int ploop_relocblks_ioc(struct ploop_device *plo, unsigned long arg)
-{
-	struct ploop_delta *delta = ploop_top_delta(plo);
-	struct ploop_relocblks_ctl ctl;
-	struct ploop_freeblks_desc *fbd = plo->fbd;
-	int i;
-	int err = 0;
-	int n_free;
-
-	return -EINVAL;
-
-	if (list_empty(&plo->map.delta_list))
-		return -ENOENT;
-
-	if (!fbd || (plo->maintenance_type != PLOOP_MNTN_FBLOADED &&
-		     plo->maintenance_type != PLOOP_MNTN_RELOC))
-		return -EINVAL;
-
-	BUG_ON(test_bit(PLOOP_S_DISCARD_LOADED, &plo->state));
-
-	if (copy_from_user(&ctl, (void*)arg, sizeof(ctl)))
-		return -EFAULT;
-
-	if (delta->level != ctl.level ||
-	    ploop_fb_get_freezed_level(plo->fbd) != ctl.level ||
-	    ploop_fb_get_alloc_head(plo->fbd) != ctl.alloc_head) {
-		return -EINVAL;
-	}
-
-	if (plo->maintenance_type == PLOOP_MNTN_RELOC)
-		goto already;
-
-	if (ctl.n_extents) {
-		struct ploop_relocblks_ctl_extent __user *extents;
-
-		extents = (void __user *)(arg + sizeof(ctl));
-
-		for (i = 0; i < ctl.n_extents; i++) {
-			struct ploop_relocblks_ctl_extent extent;
-
-			if (copy_from_user(&extent, &extents[i],
-						sizeof(extent)))
-				return release_fbd(plo, -EFAULT);
-
-			/* this extent is also present in freemap */
-			err = ploop_fb_add_reloc_extent(fbd, extent.clu,
-					extent.iblk, extent.len, extent.free);
-			if (err)
-				return release_fbd(plo, err);
-		}
-	}
-
-	ploop_quiesce(plo);
-
-	/* alloc_head must never decrease */
-	BUG_ON (delta->io.alloc_head < ploop_fb_get_alloc_head(plo->fbd));
-	n_free = ploop_fb_get_n_free(plo->fbd);
-
-	/*
-	 * before relocation start, freeblks engine could provide only
-	 * free blocks. However delta.io.alloc_head can legaly increased
-	 * in maintenance mode due to processing of interleaving WRITEs.
-	 */
-	WARN_ON (delta->io.alloc_head > ploop_fb_get_alloc_head(plo->fbd) &&
-		 n_free);
-	ploop_fb_relocation_start(plo->fbd, ctl.n_scanned);
-
-	if (!n_free || !ctl.n_extents)
-		goto truncate;
-
-	plo->maintenance_type = PLOOP_MNTN_RELOC;
-
-	ploop_relax(plo);
-
-	ploop_relocblks_process(plo);
-already:
-	err = ploop_maintenance_wait(plo);
-	if (err)
-		return err;
-
-	BUG_ON(atomic_read(&plo->maintenance_cnt));
-
-	if (plo->maintenance_type != PLOOP_MNTN_RELOC)
-		return -EALREADY;
-
-	fbd = plo->fbd;
-	BUG_ON (!fbd);
-
-	if (test_bit(PLOOP_S_ABORT, &plo->state)) {
-		clear_bit(PLOOP_S_DISCARD,&plo->state);
-
-		ploop_fb_fini(plo->fbd, -EIO);
-		plo->maintenance_type = PLOOP_MNTN_OFF;
-		return -EIO;
-	}
-
-	if (ploop_fb_get_n_relocated(fbd) != ploop_fb_get_n_relocating(fbd))
-		return release_fbd(plo, -EIO);
-
-	/* time to truncate */
-	ploop_quiesce(plo);
-truncate:
-	if ((ploop_fb_get_lost_range_len(plo->fbd) != 0) &&
-	    (delta->io.alloc_head == ploop_fb_get_alloc_head(plo->fbd))) {
-		err = delta->ops->truncate(delta, NULL,
-					   ploop_fb_get_first_lost_iblk(plo->fbd));
-		if (!err) {
-			/* See comment in dio_release_prealloced */
-			delta->io.prealloced_size = 0;
-			ctl.alloc_head = ploop_fb_get_lost_range_len(plo->fbd);
-			err = copy_to_user((void*)arg, &ctl, sizeof(ctl));
-		}
-	} else {
-		ctl.alloc_head = 0;
-		err = copy_to_user((void*)arg, &ctl, sizeof(ctl));
-	}
-
-	ploop_discard_restart(plo, err);
-
-	ploop_relax(plo);
-	return err;
-}
-
 static int ploop_getdevice_ioc(unsigned long arg)
 {
 	int err;
@@ -5267,34 +4514,10 @@  static int ploop_ioctl(struct block_device *bdev, fmode_t fmode, unsigned int cm
 	case PLOOP_IOC_BALLOON:
 		err = ploop_balloon_ioc(plo, arg);
 		break;
-	case PLOOP_IOC_FREEBLKS:
-		err = ploop_freeblks_ioc(plo, arg);
-		break;
-	case PLOOP_IOC_FBGET:
-		err = ploop_fbget_ioc(plo, arg);
-		break;
-	case PLOOP_IOC_FBFILTER:
-		err = ploop_fbfilter_ioc(plo, arg);
-		break;
-	case PLOOP_IOC_FBDROP:
-		err = ploop_fbdrop_ioc(plo);
-		break;
-	case PLOOP_IOC_RELOCBLKS:
-		err = ploop_relocblks_ioc(plo, arg);
-		break;
 	case PLOOP_IOC_GETDEVICE:
 		err = ploop_getdevice_ioc(arg);
 		break;
 
-	case PLOOP_IOC_DISCARD_INIT:
-		err = ploop_discard_init_ioc(plo);
-		break;
-	case PLOOP_IOC_DISCARD_FINI:
-		err = ploop_discard_fini_ioc(plo);
-		break;
-	case PLOOP_IOC_DISCARD_WAIT:
-		err = ploop_discard_wait_ioc(plo);
-		break;
 	case PLOOP_IOC_MAX_DELTA_SIZE:
 		err = ploop_set_max_delta_size(plo, arg);
 		break;
@@ -5438,7 +4661,6 @@  static void ploop_dev_del(struct ploop_device *plo)
 	blk_cleanup_queue(plo->queue);
 	put_disk(plo->disk);
 	rb_erase(&plo->link, &ploop_devices_tree);
-	ploop_fb_fini(plo->fbd, 0);
 	kobject_put(&plo->kobj);
 }
 
diff --git a/drivers/block/ploop/discard.c b/drivers/block/ploop/discard.c
deleted file mode 100644
index 1920ab05e20b..000000000000
--- a/drivers/block/ploop/discard.c
+++ /dev/null
@@ -1,121 +0,0 @@ 
-/*
- *  drivers/block/ploop/discard.c
- *
- *  Copyright (c) 2010-2015 Parallels IP Holdings GmbH
- *
- */
-
-#include <linux/module.h>
-#include <linux/bio.h>
-
-#include <linux/ploop/ploop.h>
-#include "discard.h"
-#include "freeblks.h"
-
-int ploop_discard_init_ioc(struct ploop_device *plo)
-{
-	struct ploop_freeblks_desc *fbd;
-	struct ploop_delta *delta = ploop_top_delta(plo);
-
-	return -EINVAL;
-
-	if (delta == NULL)
-		return -EINVAL;
-
-	if (delta->ops->id != PLOOP_FMT_PLOOP1)
-		return -EOPNOTSUPP;
-
-	if (plo->maintenance_type != PLOOP_MNTN_OFF)
-		return -EBUSY;
-
-	fbd = ploop_fb_init(plo);
-	if (!fbd)
-		return -ENOMEM;
-
-	ploop_quiesce(plo);
-
-	ploop_fb_set_freezed_level(fbd, delta->level);
-
-	plo->fbd = fbd;
-
-	atomic_set(&plo->maintenance_cnt, 0);
-	init_completion(&plo->maintenance_comp);
-	plo->maintenance_type = PLOOP_MNTN_DISCARD;
-	set_bit(PLOOP_S_DISCARD, &plo->state);
-
-	ploop_relax(plo);
-
-	return 0;
-}
-
-int ploop_discard_fini_ioc(struct ploop_device *plo)
-{
-	int ret = 0;
-	struct ploop_request *preq, *tmp;
-	LIST_HEAD(drop_list);
-
-	return -EINVAL;
-
-	if (!test_and_clear_bit(PLOOP_S_DISCARD, &plo->state))
-		return 0;
-
-	ploop_quiesce(plo);
-
-	spin_lock_irq(&plo->lock);
-	list_for_each_entry_safe(preq, tmp, &plo->entry_queue, list)
-		if (test_bit(PLOOP_REQ_DISCARD, &preq->state)) {
-			list_move(&preq->list, &drop_list);
-			ploop_entry_qlen_dec(preq);
-		}
-	spin_unlock_irq(&plo->lock);
-
-	if (!list_empty(&drop_list))
-		ploop_preq_drop(plo, &drop_list);
-
-	if (plo->maintenance_type != PLOOP_MNTN_DISCARD) {
-		ret = -EBUSY;
-		goto out;
-	}
-
-	ploop_fb_fini(plo->fbd, -EOPNOTSUPP);
-
-	clear_bit(PLOOP_S_DISCARD_LOADED, &plo->state);
-
-	plo->maintenance_type = PLOOP_MNTN_OFF;
-	complete(&plo->maintenance_comp);
-
-out:
-	ploop_relax(plo);
-
-	return ret;
-}
-
-int ploop_discard_wait_ioc(struct ploop_device *plo)
-{
-	int err;
-
-	return -EINVAL;
-
-	if (!test_bit(PLOOP_S_DISCARD, &plo->state))
-		return 0;
-
-	if (plo->maintenance_type == PLOOP_MNTN_FBLOADED)
-		return 1;
-
-	if (plo->maintenance_type != PLOOP_MNTN_DISCARD)
-		return -EINVAL;
-
-	err = ploop_maintenance_wait(plo);
-	if (err)
-		goto out;
-
-	/* maintenance_cnt is zero without discard requests,
-	 * in this case ploop_maintenance_wait returns 0
-	 * instead of ERESTARTSYS */
-	if (test_bit(PLOOP_S_DISCARD_LOADED, &plo->state)) {
-		err = 1;
-	} else if (signal_pending(current))
-		err = -ERESTARTSYS;
-out:
-	return err;
-}
diff --git a/drivers/block/ploop/discard.h b/drivers/block/ploop/discard.h
deleted file mode 100644
index a8e7e4e59b09..000000000000
--- a/drivers/block/ploop/discard.h
+++ /dev/null
@@ -1,15 +0,0 @@ 
-/*
- *  drivers/block/ploop/discard.h
- *
- *  Copyright (c) 2010-2015 Parallels IP Holdings GmbH
- *
- */
-
-#ifndef _LINUX_PLOOP_DISCARD_H_
-#define _LINUX_PLOOP_DISCARD_H_
-
-extern int ploop_discard_init_ioc(struct ploop_device *plo);
-extern int ploop_discard_fini_ioc(struct ploop_device *plo);
-extern int ploop_discard_wait_ioc(struct ploop_device *plo);
-
-#endif // _LINUX_PLOOP_DISCARD_H_
diff --git a/drivers/block/ploop/freeblks.c b/drivers/block/ploop/freeblks.c
deleted file mode 100644
index ab907a39ac65..000000000000
--- a/drivers/block/ploop/freeblks.c
+++ /dev/null
@@ -1,1110 +0,0 @@ 
-/*
- *  drivers/block/ploop/freeblks.c
- *
- *  Copyright (c) 2010-2015 Parallels IP Holdings GmbH
- *
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/file.h>
-#include <linux/bio.h>
-#include <linux/interrupt.h>
-#include <linux/buffer_head.h>
-#include <linux/kthread.h>
-
-#include <trace/events/block.h>
-
-#include <linux/ploop/ploop.h>
-#include "freeblks.h"
-
-#define MIN(a, b) (a < b ? a : b)
-
-struct ploop_freeblks_extent
-{
-	struct list_head list; /* List link */
-
-	cluster_t clu;
-	iblock_t  iblk;
-	u32	  len;
-
-};
-
-struct ploop_relocblks_extent
-{
-	struct list_head list; /* List link */
-
-	cluster_t clu;
-	iblock_t  iblk;
-	u32	  len;
-	u32	  free;	/* this extent is also present in freemap */
-};
-
-struct ploop_fextent_ptr {
-	struct ploop_freeblks_extent *ext;
-	u32 off;
-};
-
-struct ploop_rextent_ptr {
-	struct ploop_relocblks_extent *ext;
-	u32 off;
-};
-
-struct ploop_freeblks_desc {
-	struct ploop_device *plo;
-
-	int fbd_n_free;	       /* # free blocks remaining
-				  (i.e. "not re-used") */
-
-	/* fbd_ffb.ext->clu + fbd_ffb.off can be used as
-	 * 'clu of first free block to reuse' for WRITE ops */
-	struct ploop_fextent_ptr fbd_ffb; /* 'ffb' stands for
-					     'first free block' */
-
-	/* fbd_lfb.ext->clu + fbd_lfb.off can be used as
-	 * 'clu of first block to overwrite' (draining reloc range from end) */
-	struct ploop_fextent_ptr fbd_lfb; /* 'lfb' stands for
-					     'last free block for relocation'*/
-
-	/* fbd_reloc_extents[fbd->fbd_last_reloc_extent].clu +
-	 * fbd_last_reloc_off can be used as 'clu of first block to relocate'
-	 * (draining reloc range from end)
-	 * NB: ffb and lfb above deal with free_list, while lrb deals with
-	 * reloc_list! */
-	struct ploop_rextent_ptr fbd_lrb; /* 'lrb' stands for
-					     'last block to relocate' */
-
-	/* counters to trace the progress of relocation */
-	int fbd_n_relocated;  /* # blocks actually relocated */
-	int fbd_n_relocating; /* # blocks whose relocation was at
-				   least started */
-
-	/* lost_range: [fbd_first_lost_iblk ..
-	 *		fbd_first_lost_iblk + fbd_lost_range_len - 1] */
-	iblock_t fbd_first_lost_iblk;
-	int	 fbd_lost_range_len;
-	int	 fbd_lost_range_addon; /* :)) */
-
-	/* any reloc request resides there while it's "in progress" */
-	struct rb_root		reloc_tree;
-
-	/* list of ploop_request-s for PLOOP_REQ_ZERO ops: firstly zero index
-	 * for PLOOP_REQ_ZERO req_cluster, then schedule ordinary request
-	 * pinned to given PLOOP_REQ_ZERO request */
-	struct list_head	free_zero_list;
-
-	/* storage for free-block extents: list for now */
-	struct list_head	fbd_free_list;
-
-	/* storage for reloc-block extents: list for now */
-	struct list_head	fbd_reloc_list;
-
-	int	 fbd_freezed_level; /* for sanity - level on
-				     * PLOOP_IOC_FREEBLKS stage */
-
-	struct bio_list	fbd_dbl; /* dbl stands for 'discard bio list' */
-};
-
-int ploop_fb_get_n_relocated(struct ploop_freeblks_desc *fbd)
-{
-	return fbd->fbd_n_relocated;
-}
-int ploop_fb_get_n_relocating(struct ploop_freeblks_desc *fbd)
-{
-	return fbd->fbd_n_relocating;
-}
-int ploop_fb_get_n_free(struct ploop_freeblks_desc *fbd)
-{
-	return fbd->fbd_n_free;
-}
-iblock_t ploop_fb_get_alloc_head(struct ploop_freeblks_desc *fbd)
-{
-	return fbd->fbd_first_lost_iblk + fbd->fbd_lost_range_len;
-}
-int ploop_fb_get_lost_range_len(struct ploop_freeblks_desc *fbd)
-{
-	return fbd->fbd_lost_range_len;
-}
-iblock_t ploop_fb_get_first_lost_iblk(struct ploop_freeblks_desc *fbd)
-{
-	return fbd->fbd_first_lost_iblk;
-}
-
-int ploop_fb_get_freezed_level(struct ploop_freeblks_desc *fbd)
-{
-	return fbd->fbd_freezed_level;
-}
-void ploop_fb_set_freezed_level(struct ploop_freeblks_desc *fbd, int level)
-{
-	fbd->fbd_freezed_level = level;
-}
-
-void ploop_fb_add_reloc_req(struct ploop_freeblks_desc *fbd,
-			    struct ploop_request *preq)
-{
-	struct rb_node ** p;
-	struct rb_node *parent = NULL;
-	struct ploop_request * pr;
-
-	if (fbd == NULL)
-		return;
-
-	p = &fbd->reloc_tree.rb_node;
-	while (*p) {
-		parent = *p;
-		pr = rb_entry(parent, struct ploop_request, reloc_link);
-		BUG_ON (preq->src_iblock == pr->src_iblock);
-
-		if (preq->src_iblock < pr->src_iblock)
-			p = &(*p)->rb_left;
-		else
-			p = &(*p)->rb_right;
-	}
-
-	rb_link_node(&preq->reloc_link, parent, p);
-	rb_insert_color(&preq->reloc_link, &fbd->reloc_tree);
-}
-
-void ploop_fb_del_reloc_req(struct ploop_freeblks_desc *fbd,
-			    struct ploop_request *preq)
-{
-	BUG_ON (fbd == NULL);
-
-	rb_erase(&preq->reloc_link, &fbd->reloc_tree);
-}
-
-int ploop_fb_check_reloc_req(struct ploop_freeblks_desc *fbd,
-			     struct ploop_request *preq,
-			     unsigned long pin_state)
-{
-	struct rb_node *n;
-	struct ploop_request * p;
-
-	BUG_ON (fbd == NULL);
-	BUG_ON (preq->iblock == 0);
-	BUG_ON (preq->iblock >= fbd->fbd_first_lost_iblk);
-
-	n = fbd->reloc_tree.rb_node;
-	if (n == NULL)
-		return 0;
-
-	while (n) {
-		p = rb_entry(n, struct ploop_request, reloc_link);
-
-		if (preq->iblock < p->src_iblock)
-			n = n->rb_left;
-		else if (preq->iblock > p->src_iblock)
-			n = n->rb_right;
-		else {
-			spin_lock_irq(&fbd->plo->lock);
-			preq->eng_state = pin_state;
-			list_add_tail(&preq->list, &p->delay_list);
-			spin_unlock_irq(&fbd->plo->lock);
-			return 1;
-		}
-	}
-	return 0;
-}
-
-int ploop_fb_copy_freeblks_to_user(struct ploop_freeblks_desc *fbd, void *arg,
-				   struct ploop_freeblks_ctl *ctl)
-{
-	int   rc = 0;
-	int   n	 = 0;
-	struct ploop_freeblks_extent	 *fextent;
-	struct ploop_freeblks_ctl_extent  cext;
-
-	memset(&cext, 0, sizeof(cext));
-	list_for_each_entry(fextent, &fbd->fbd_free_list, list)
-		if (ctl->n_extents) {
-			int off = offsetof(struct ploop_freeblks_ctl,
-					   extents[n]);
-			if (n++ >= ctl->n_extents) {
-				rc = -ENOSPC;
-				break;
-			}
-
-			cext.clu  = fextent->clu;
-			cext.iblk = fextent->iblk;
-			cext.len  = fextent->len;
-
-			rc = copy_to_user((u8*)arg + off, &cext, sizeof(cext));
-			if (rc)
-				break;
-		} else {
-			n++;
-		}
-
-	if (!rc) {
-		ctl->n_extents = n;
-		rc = copy_to_user((void*)arg, ctl, sizeof(*ctl));
-	}
-
-	return rc;
-}
-
-int ploop_fb_filter_freeblks(struct ploop_freeblks_desc *fbd, unsigned long minlen)
-{
-	struct ploop_freeblks_extent *fextent, *n;
-
-	list_for_each_entry_safe(fextent, n, &fbd->fbd_free_list, list)
-		if (fextent->len < minlen) {
-			list_del(&fextent->list);
-			fbd->fbd_n_free -= fextent->len;
-			kfree(fextent);
-		}
-
-	if (list_empty(&fbd->fbd_free_list))
-		fbd->fbd_ffb.ext = NULL;
-	else
-		fbd->fbd_ffb.ext = list_entry(fbd->fbd_free_list.next,
-						struct ploop_freeblks_extent,
-						list);
-	fbd->fbd_ffb.off = 0;
-
-	return fbd->fbd_n_free;
-}
-
-struct ploop_request *
-ploop_fb_get_zero_request(struct ploop_freeblks_desc *fbd)
-{
-	struct ploop_request * preq;
-
-	BUG_ON (fbd == NULL);
-	BUG_ON (list_empty(&fbd->free_zero_list));
-
-	preq = list_entry(fbd->free_zero_list.next,
-			  struct ploop_request, list);
-	list_del(&preq->list);
-	return preq;
-}
-
-void ploop_fb_put_zero_request(struct ploop_freeblks_desc *fbd,
-			       struct ploop_request *preq)
-{
-	list_add(&preq->list, &fbd->free_zero_list);
-}
-
-static iblock_t ffb_iblk(struct ploop_freeblks_desc *fbd)
-{
-	return fbd->fbd_ffb.ext->iblk + fbd->fbd_ffb.off;
-}
-static cluster_t ffb_clu(struct ploop_freeblks_desc *fbd)
-{
-	return fbd->fbd_ffb.ext->clu + fbd->fbd_ffb.off;
-}
-static iblock_t lfb_iblk(struct ploop_freeblks_desc *fbd)
-{
-	return fbd->fbd_lfb.ext->iblk + fbd->fbd_lfb.off;
-}
-static cluster_t lfb_clu(struct ploop_freeblks_desc *fbd)
-{
-	return fbd->fbd_lfb.ext->clu + fbd->fbd_lfb.off;
-}
-static iblock_t lrb_iblk(struct ploop_freeblks_desc *fbd)
-{
-	return fbd->fbd_lrb.ext->iblk + fbd->fbd_lrb.off;
-}
-
-static iblock_t get_first_reloc_iblk(struct ploop_freeblks_desc *fbd)
-{
-	struct ploop_relocblks_extent *r_extent;
-
-	BUG_ON (list_empty(&fbd->fbd_reloc_list));
-	r_extent = list_entry(fbd->fbd_reloc_list.next,
-			      struct ploop_relocblks_extent, list);
-	return r_extent->iblk;
-}
-
-static void advance_ffb_simple(struct ploop_freeblks_desc *fbd)
-{
-	BUG_ON (fbd->fbd_ffb.ext == NULL);
-
-	if (fbd->fbd_ffb.off < fbd->fbd_ffb.ext->len - 1) {
-		fbd->fbd_ffb.off++;
-	} else {
-		if (fbd->fbd_ffb.ext->list.next == &fbd->fbd_free_list)
-			fbd->fbd_ffb.ext = NULL;
-		else
-			fbd->fbd_ffb.ext = list_entry(fbd->fbd_ffb.ext->list.next,
-						      struct ploop_freeblks_extent,
-						      list);
-		fbd->fbd_ffb.off = 0;
-	}
-
-	if (fbd->fbd_ffb.ext != NULL &&
-	    ffb_iblk(fbd) >= fbd->fbd_first_lost_iblk) {
-		/* invalidate ffb */
-		fbd->fbd_ffb.ext = NULL;
-		fbd->fbd_ffb.off = 0;
-	}
-}
-
-static void advance_lrb(struct ploop_freeblks_desc *fbd)
-{
-	iblock_t skip = 0;
-	BUG_ON (fbd->fbd_lrb.ext == NULL);
-
-	if (likely(fbd->fbd_lrb.off)) {
-		fbd->fbd_lrb.off--;
-	} else {
-		struct ploop_relocblks_extent *r_extent = fbd->fbd_lrb.ext;
-		/* here 'skip' means: [new_lrb_ext]<--skip-->[r_extent] */
-
-		if (fbd->fbd_lrb.ext->list.prev == &fbd->fbd_reloc_list) {
-			BUG_ON (fbd->fbd_lost_range_addon < 0);
-			skip = fbd->fbd_lost_range_addon;
-			fbd->fbd_lrb.ext = NULL;
-		} else {
-			fbd->fbd_lrb.ext = list_entry(fbd->fbd_lrb.ext->list.prev,
-						      struct ploop_relocblks_extent,
-						      list);
-			fbd->fbd_lrb.off = fbd->fbd_lrb.ext->len - 1;
-			BUG_ON (r_extent->iblk < fbd->fbd_lrb.ext->iblk +
-						 fbd->fbd_lrb.ext->len);
-			skip = r_extent->iblk - (fbd->fbd_lrb.ext->iblk +
-						 fbd->fbd_lrb.ext->len);
-		}
-	}
-
-	fbd->fbd_first_lost_iblk -= 1 + skip;
-	fbd->fbd_lost_range_len	 += 1 + skip;
-
-	if (fbd->fbd_ffb.ext != NULL &&
-	    ffb_iblk(fbd) >= fbd->fbd_first_lost_iblk) {
-		/* invalidate ffb */
-		fbd->fbd_ffb.ext = NULL;
-		fbd->fbd_ffb.off = 0;
-	}
-
-	BUG_ON(fbd->fbd_n_free <= 0);
-	fbd->fbd_n_free--;
-}
-
-static int split_fb_extent(struct ploop_freeblks_extent *extent, u32 *off_p,
-			   struct ploop_freeblks_desc *fbd)
-{
-	struct ploop_freeblks_extent *new_extent;
-
-	new_extent = kzalloc(sizeof(*new_extent), GFP_KERNEL);
-	if (new_extent == NULL) {
-		printk("Can't allocate new freeblks extent for splittig!\n");
-		return -ENOMEM;
-	}
-
-	new_extent->clu	 = extent->clu	+ *off_p + 1;
-	new_extent->iblk = extent->iblk + *off_p + 1;
-	new_extent->len	 = extent->len	- *off_p - 1;
-
-	extent->len  = *off_p;
-
-	list_add(&new_extent->list, &extent->list);
-
-	(*off_p)--;
-	return 0;
-}
-
-static int advance_lfb_left(struct ploop_freeblks_desc *fbd)
-{
-	int rc = 0;
-	struct ploop_freeblks_extent *lfb_ext = fbd->fbd_lfb.ext;
-
-	BUG_ON (fbd->fbd_ffb.ext == NULL);
-	BUG_ON (lfb_ext == NULL);
-	BUG_ON (ffb_iblk(fbd) > lfb_iblk(fbd));
-
-	if (ffb_iblk(fbd) == lfb_iblk(fbd)) {
-		/* invalidate lfb */
-		fbd->fbd_lfb.ext = NULL;
-		fbd->fbd_lfb.off = 0;
-		advance_ffb_simple(fbd);
-		return 0;
-	}
-
-	if (fbd->fbd_lfb.off) {
-		if (fbd->fbd_lfb.off == lfb_ext->len - 1) {
-			lfb_ext->len--;
-			fbd->fbd_lfb.off--;
-		} else {
-			rc = split_fb_extent(lfb_ext, &fbd->fbd_lfb.off, fbd);
-		}
-	} else {
-		BUG_ON (lfb_ext->list.prev == &fbd->fbd_free_list);
-		BUG_ON (lfb_ext == fbd->fbd_ffb.ext);
-
-		lfb_ext->clu++;
-		lfb_ext->iblk++;
-		lfb_ext->len--;
-
-		fbd->fbd_lfb.ext = list_entry(lfb_ext->list.prev,
-					      struct ploop_freeblks_extent,
-					      list);
-		fbd->fbd_lfb.off = fbd->fbd_lfb.ext->len - 1;
-
-		if (lfb_ext->len == 0) {
-			list_del(&lfb_ext->list);
-			kfree(lfb_ext);
-		}
-	}
-
-	BUG_ON (fbd->fbd_ffb.ext == NULL);
-	BUG_ON (fbd->fbd_lfb.ext == NULL);
-	BUG_ON (lfb_iblk(fbd) < ffb_iblk(fbd));
-	return rc;
-}
-
-int ploop_fb_get_reloc_block(struct ploop_freeblks_desc *fbd,
-			     cluster_t *from_clu_p, iblock_t *from_iblk_p,
-			     cluster_t *to_clu_p, iblock_t *to_iblk_p,
-			     u32 *free_p)
-{
-	cluster_t from_clu, to_clu;
-	iblock_t  from_iblk, to_iblk;
-	u32 free;
-	struct ploop_relocblks_extent *r_extent = fbd->fbd_lrb.ext;
-
-	if (!fbd)
-		return -1;
-
-	/* whole range is drained? */
-	if (r_extent == NULL)
-		return -1;
-
-	BUG_ON (fbd->fbd_lrb.off >= r_extent->len);
-
-	from_clu  = r_extent->clu  + fbd->fbd_lrb.off;
-	from_iblk = r_extent->iblk + fbd->fbd_lrb.off;
-	free	  = r_extent->free;
-
-	/* from_iblk is in range to relocate, but it's marked as free.
-	 * This means that we only need to zero its index, no actual
-	 * relocation needed. Such an operation doesn't consume free
-	 * block that fbd_last_free refers to */
-	if (free) {
-		/* The block we're going to zero-index was already re-used? */
-		if (fbd->fbd_ffb.ext == NULL || ffb_iblk(fbd) > from_iblk)
-			return -1;
-
-		BUG_ON (fbd->fbd_ffb.off  >= fbd->fbd_ffb.ext->len);
-
-		to_iblk = ~0U;
-		to_clu	= ~0U;
-	} else {
-		/* run out of free blocks which can be used as destination
-		 * for relocation ? */
-		if (fbd->fbd_lfb.ext == NULL)
-			return -1;
-
-		BUG_ON (fbd->fbd_ffb.ext == NULL);
-		BUG_ON (fbd->fbd_ffb.off  >= fbd->fbd_ffb.ext->len);
-		BUG_ON (fbd->fbd_lfb.off  >= fbd->fbd_lfb.ext->len);
-		BUG_ON (ffb_iblk(fbd) > lfb_iblk(fbd));
-
-		to_clu	= lfb_clu(fbd);
-		to_iblk = lfb_iblk(fbd);
-
-		if (advance_lfb_left(fbd)) {
-			/* Error implies stopping relocation */
-			fbd->fbd_lrb.ext = NULL;
-			fbd->fbd_lrb.off = 0;
-			return -1;
-		}
-	}
-
-	/* consume one block from the end of reloc list */
-	advance_lrb(fbd);
-
-	fbd->fbd_n_relocating++;
-
-	*from_clu_p  = from_clu;
-	*from_iblk_p = from_iblk;
-	*to_clu_p    = to_clu;
-	*to_iblk_p   = to_iblk;
-	*free_p	     = free;
-	return 0;
-}
-
-void ploop_fb_relocate_req_completed(struct ploop_freeblks_desc *fbd)
-{
-	fbd->fbd_n_relocated++;
-}
-
-static void advance_lfb_right(struct ploop_freeblks_desc *fbd)
-{
-	iblock_t iblk = get_first_reloc_iblk(fbd);
-
-	if (fbd->fbd_lfb.off < fbd->fbd_lfb.ext->len - 1) {
-		if (fbd->fbd_lfb.ext->iblk + fbd->fbd_lfb.off + 1 < iblk) {
-			fbd->fbd_lfb.off++;
-		}
-	} else if (fbd->fbd_lfb.ext->list.next != &fbd->fbd_free_list) {
-		struct ploop_freeblks_extent *f_extent;
-		f_extent = list_entry(fbd->fbd_lfb.ext->list.next,
-				      struct ploop_freeblks_extent,
-				      list);
-		if (f_extent->iblk < iblk) {
-			fbd->fbd_lfb.ext = f_extent;
-			fbd->fbd_lfb.off = 0;
-		}
-	}
-
-	/* invalidating ffb always implies invalidating lfb */
-	BUG_ON (fbd->fbd_ffb.ext == NULL && fbd->fbd_lfb.ext != NULL);
-
-	/* caller has just advanced ffb, but we must keep lfb intact
-	 * if next-free-block (following to lfb) is in reloc-range */
-	if (fbd->fbd_ffb.ext != NULL && fbd->fbd_lfb.ext != NULL &&
-	    lfb_iblk(fbd) < ffb_iblk(fbd)) {
-		fbd->fbd_lfb.ext = NULL;
-		fbd->fbd_lfb.off = 0;
-	}
-}
-
-static void trim_reloc_list_one_blk(struct ploop_freeblks_desc *fbd)
-{
-	struct ploop_relocblks_extent *r_extent_first;
-	iblock_t iblk = lrb_iblk(fbd);
-	int invalidate = 0;
-
-	BUG_ON (list_empty(&fbd->fbd_reloc_list));
-	r_extent_first = list_entry(fbd->fbd_reloc_list.next,
-				    struct ploop_relocblks_extent, list);
-
-	if (r_extent_first->len > 1) {
-		fbd->fbd_lost_range_addon = 0;
-		r_extent_first->iblk++;
-		r_extent_first->clu++;
-		r_extent_first->len--;
-		if (iblk < r_extent_first->iblk) {
-			invalidate = 1;
-		} else if (r_extent_first == fbd->fbd_lrb.ext) {
-			BUG_ON (fbd->fbd_lrb.off == 0);
-			fbd->fbd_lrb.off--;
-		}
-	} else {
-		if (r_extent_first == fbd->fbd_lrb.ext) {
-			invalidate = 1;
-		} else {
-			struct ploop_relocblks_extent *r_extent;
-			BUG_ON (r_extent_first->list.next ==
-				&fbd->fbd_reloc_list);
-			r_extent = list_entry(r_extent_first->list.next,
-					      struct ploop_relocblks_extent,
-					      list);
-			fbd->fbd_lost_range_addon = r_extent->iblk -
-				(r_extent_first->iblk + r_extent_first->len);
-		}
-		list_del(&r_extent_first->list);
-		kfree(r_extent_first);
-	}
-
-	if (invalidate) {
-		/* invalidate both lfb and lrb */
-		fbd->fbd_lrb.ext = NULL;
-		fbd->fbd_lrb.off = 0;
-		if (fbd->fbd_lfb.ext != NULL) {
-			fbd->fbd_lfb.ext = NULL;
-			fbd->fbd_lfb.off = 0;
-		}
-	}
-}
-
-static void advance_ffb(struct ploop_freeblks_desc *fbd)
-{
-	BUG_ON (fbd->fbd_ffb.ext == NULL);
-	BUG_ON (fbd->fbd_lfb.ext != NULL && ffb_iblk(fbd) > lfb_iblk(fbd));
-
-	if (fbd->fbd_ffb.off < fbd->fbd_ffb.ext->len - 1) {
-		fbd->fbd_ffb.off++;
-	} else {
-		if (fbd->fbd_ffb.ext->list.next == &fbd->fbd_free_list) {
-			BUG_ON (fbd->fbd_lfb.ext != NULL &&
-				ffb_iblk(fbd) != lfb_iblk(fbd));
-			fbd->fbd_ffb.ext = NULL;
-		} else {
-			fbd->fbd_ffb.ext = list_entry(fbd->fbd_ffb.ext->list.next,
-						      struct ploop_freeblks_extent,
-						      list);
-		}
-		fbd->fbd_ffb.off = 0;
-	}
-
-	if (fbd->fbd_ffb.ext == NULL && fbd->fbd_lfb.ext != NULL) {
-		/* invalidate lfb */
-		fbd->fbd_lfb.ext = NULL;
-		fbd->fbd_lfb.off = 0;
-		return;
-	}
-
-	if (fbd->fbd_ffb.ext != NULL &&
-	    ffb_iblk(fbd) >= fbd->fbd_first_lost_iblk) {
-		/* invalidate both ffb and lfb */
-		fbd->fbd_ffb.ext = NULL;
-		fbd->fbd_ffb.off = 0;
-		fbd->fbd_lfb.ext = NULL;
-		fbd->fbd_lfb.off = 0;
-	}
-
-	/* nothing to do anymore if relocation process is completed */
-	if (fbd->fbd_lrb.ext == NULL)
-		return;
-
-	trim_reloc_list_one_blk(fbd);
-
-	/* trim could invalidate both lrb and lfb */
-	if (fbd->fbd_lrb.ext == NULL || fbd->fbd_lfb.ext == NULL)
-		return;
-
-	advance_lfb_right(fbd);
-}
-
-int ploop_fb_get_free_block(struct ploop_freeblks_desc *fbd,
-			    cluster_t *clu, iblock_t *iblk)
-{
-	if (!fbd)
-		return -1;
-
-	if (fbd->fbd_ffb.ext == NULL) {
-		BUG_ON (fbd->fbd_lfb.ext != NULL);
-		BUG_ON (fbd->fbd_lost_range_len < 0);
-
-		if (fbd->fbd_lost_range_len == 0)
-			return -1;
-
-		*iblk = fbd->fbd_first_lost_iblk++;
-		fbd->fbd_lost_range_len--;
-
-		if (fbd->fbd_lrb.ext != NULL) {
-			/* stop relocation process */
-			fbd->fbd_lrb.ext = NULL;
-			fbd->fbd_lrb.off = 0;
-		}
-
-		return 0;
-	}
-
-	BUG_ON (ffb_iblk(fbd) >= fbd->fbd_first_lost_iblk);
-	BUG_ON (fbd->fbd_n_free <= 0);
-
-	*clu = ffb_clu(fbd);
-	fbd->fbd_n_free--;
-
-	if (fbd->plo->maintenance_type == PLOOP_MNTN_RELOC)
-		advance_ffb(fbd);
-	else
-		advance_ffb_simple(fbd);
-
-	BUG_ON (fbd->fbd_ffb.ext == NULL && fbd->fbd_n_free != 0);
-	BUG_ON (fbd->fbd_ffb.ext != NULL && fbd->fbd_n_free == 0);
-
-	return 1;
-}
-
-static void fbd_complete_bio(struct ploop_freeblks_desc *fbd, int err)
-{
-	struct ploop_device *plo = fbd->plo;
-	unsigned int nr_completed = 0;
-
-	while (fbd->fbd_dbl.head) {
-		struct bio * bio = fbd->fbd_dbl.head;
-		fbd->fbd_dbl.head = bio->bi_next;
-		bio->bi_next = NULL;
-		BIO_ENDIO(plo->queue, bio, err);
-		nr_completed++;
-	}
-	fbd->fbd_dbl.tail = NULL;
-
-	spin_lock_irq(&plo->lock);
-	plo->bio_total -= nr_completed;
-	if (!bio_list_empty(&plo->bio_discard_list) &&
-	    waitqueue_active(&plo->waitq))
-		wake_up_interruptible(&plo->waitq);
-	spin_unlock_irq(&plo->lock);
-}
-
-void ploop_fb_reinit(struct ploop_freeblks_desc *fbd, int err)
-{
-	fbd_complete_bio(fbd, err);
-
-	while (!list_empty(&fbd->fbd_free_list)) {
-		struct ploop_freeblks_extent *fblk_extent;
-
-		fblk_extent = list_first_entry(&fbd->fbd_free_list,
-					       struct ploop_freeblks_extent,
-					       list);
-		list_del(&fblk_extent->list);
-		kfree(fblk_extent);
-	}
-
-	while (!list_empty(&fbd->fbd_reloc_list)) {
-		struct ploop_relocblks_extent *rblk_extent;
-
-		rblk_extent = list_first_entry(&fbd->fbd_reloc_list,
-					       struct ploop_relocblks_extent,
-					       list);
-		list_del(&rblk_extent->list);
-		kfree(rblk_extent);
-	}
-
-	fbd->fbd_n_free = 0;
-	fbd->fbd_ffb.ext = NULL;
-	fbd->fbd_lfb.ext = NULL;
-	fbd->fbd_lrb.ext = NULL;
-	fbd->fbd_ffb.off = 0;
-	fbd->fbd_lfb.off = 0;
-	fbd->fbd_lrb.off = 0;
-	fbd->fbd_n_relocated = fbd->fbd_n_relocating = 0;
-	fbd->fbd_lost_range_len = 0;
-	fbd->fbd_lost_range_addon = 0;
-
-	BUG_ON(!RB_EMPTY_ROOT(&fbd->reloc_tree));
-}
-
-struct ploop_freeblks_desc *ploop_fb_init(struct ploop_device *plo)
-{
-	struct ploop_freeblks_desc *fbd;
-	int i;
-
-	fbd = kmalloc(sizeof(struct ploop_freeblks_desc), GFP_KERNEL);
-	if (fbd == NULL)
-		return NULL;
-
-	fbd->fbd_dbl.tail = fbd->fbd_dbl.head = NULL;
-	INIT_LIST_HEAD(&fbd->fbd_free_list);
-	INIT_LIST_HEAD(&fbd->fbd_reloc_list);
-	fbd->reloc_tree = RB_ROOT;
-	fbd->fbd_freezed_level = -1;
-
-	fbd->plo = plo;
-
-	ploop_fb_reinit(fbd, 0);
-
-	INIT_LIST_HEAD(&fbd->free_zero_list);
-	for (i = 0; i < plo->tune.max_requests; i++) {
-		struct ploop_request * preq;
-		preq = kzalloc(sizeof(struct ploop_request), GFP_KERNEL);
-		if (preq == NULL)
-			goto fb_init_failed;
-
-		preq->plo = plo;
-		INIT_LIST_HEAD(&preq->delay_list);
-		list_add(&preq->list, &fbd->free_zero_list);
-	}
-
-	return fbd;
-
-fb_init_failed:
-	ploop_fb_fini(fbd, -ENOMEM);
-	return NULL;
-}
-
-void ploop_fb_fini(struct ploop_freeblks_desc *fbd, int err)
-{
-	struct ploop_device *plo;
-
-	if (fbd == NULL)
-		return;
-
-	plo = fbd->plo;
-	BUG_ON (plo == NULL);
-
-	fbd_complete_bio(fbd, err);
-
-	while (!list_empty(&fbd->fbd_free_list)) {
-		struct ploop_freeblks_extent *fblk_extent;
-
-		fblk_extent = list_first_entry(&fbd->fbd_free_list,
-					       struct ploop_freeblks_extent,
-					       list);
-		list_del(&fblk_extent->list);
-		kfree(fblk_extent);
-	}
-
-	while (!list_empty(&fbd->fbd_reloc_list)) {
-		struct ploop_relocblks_extent *rblk_extent;
-
-		rblk_extent = list_first_entry(&fbd->fbd_reloc_list,
-					       struct ploop_relocblks_extent,
-					       list);
-		list_del(&rblk_extent->list);
-		kfree(rblk_extent);
-	}
-
-	while (!list_empty(&fbd->free_zero_list)) {
-		struct ploop_request * preq;
-
-		preq = list_first_entry(&fbd->free_zero_list,
-					struct ploop_request,
-					list);
-		list_del(&preq->list);
-		kfree(preq);
-	}
-
-	kfree(fbd);
-	plo->fbd = NULL;
-}
-
-int ploop_fb_add_free_extent(struct ploop_freeblks_desc *fbd,
-			     cluster_t clu, iblock_t iblk, u32 len)
-{
-	struct ploop_freeblks_extent *fblk_extent;
-	struct ploop_freeblks_extent *ex;
-
-	if (len == 0) {
-		printk("ploop_fb_add_free_extent(): empty extent! (%u/%u)\n",
-		       clu, iblk);
-		return 0;
-	}
-
-	list_for_each_entry_reverse(ex, &fbd->fbd_free_list, list)
-		if (ex->iblk < iblk)
-			break;
-
-	if (ex->list.next != &fbd->fbd_free_list) {
-		struct ploop_freeblks_extent *tmp;
-		tmp = list_entry(ex->list.next, struct ploop_freeblks_extent, list);
-
-		if (iblk + len > tmp->iblk) {
-			int c = &ex->list != &fbd->fbd_free_list;
-			printk("ploop_fb_add_free_extent(): next (%u %u %u) "
-			       "intersects with (%u %u %u); ex (%u %u %d)\n",
-			       tmp->clu, tmp->iblk, tmp->len, clu, iblk, len,
-			       c ? ex->clu : 0, c ? ex->iblk : 0, c ? ex->len : -1);
-			return -EINVAL;
-		}
-	}
-
-	if (&ex->list != &fbd->fbd_free_list) {
-		if (ex->iblk + ex->len > iblk) {
-			struct ploop_freeblks_extent *t = NULL;
-			if (ex->list.next != &fbd->fbd_free_list)
-				t = list_entry(ex->list.next, struct ploop_freeblks_extent, list);
-			printk("ploop_fb_add_free_extent(): ex (%u %u %u) "
-			       "intersects with (%u %u %u); next (%u %u %d)\n",
-			       ex->clu, ex->iblk, ex->len, clu, iblk, len,
-			       t ? t->clu : 0, t ? t->iblk : 0, t ? t->len : -1);
-			return -EINVAL;
-		}
-	}
-
-	fblk_extent = kzalloc(sizeof(*fblk_extent), GFP_KERNEL);
-	if (fblk_extent == NULL)
-		return -ENOMEM;
-
-	fblk_extent->clu  = clu;
-	fblk_extent->iblk = iblk;
-	fblk_extent->len  = len;
-
-	list_add(&fblk_extent->list, &ex->list);
-
-	fbd->fbd_n_free	 += len;
-
-	fbd->fbd_ffb.ext = list_entry(fbd->fbd_free_list.next, struct ploop_freeblks_extent, list);
-	fbd->fbd_ffb.off = 0;
-
-	return 0;
-}
-
-int ploop_fb_add_reloc_extent(struct ploop_freeblks_desc *fbd,
-			      cluster_t clu, iblock_t iblk, u32 len, u32 free)
-{
-	struct ploop_relocblks_extent *rblk_extent;
-
-	if (len == 0) {
-		printk("ploop_fb_add_reloc_extent(): empty extent! (%u/%u)\n",
-		       clu, iblk);
-		return 0;
-	}
-
-	if (!list_empty(&fbd->fbd_reloc_list)) {
-		rblk_extent = list_entry(fbd->fbd_reloc_list.prev,
-					 struct ploop_relocblks_extent, list);
-		if (rblk_extent->iblk + rblk_extent->len > iblk) {
-			printk("ploop_fb_add_reloc_extent(): extents should be sorted\n");
-			return -EINVAL;
-		}
-
-		if (rblk_extent->list.next != &fbd->fbd_reloc_list) {
-			rblk_extent = list_entry(rblk_extent->list.next,
-					 struct ploop_relocblks_extent, list);
-			if (iblk + len > rblk_extent->iblk) {
-				printk("ploop_fb_add_reloc_extent(): intersected extents\n");
-				return -EINVAL;
-			}
-		}
-	}
-
-	rblk_extent = kzalloc(sizeof(*rblk_extent), GFP_KERNEL);
-	if (rblk_extent == NULL)
-		return -ENOMEM;
-
-	rblk_extent->clu  = clu;
-	rblk_extent->iblk = iblk;
-	rblk_extent->len  = len;
-	rblk_extent->free = free;
-
-	list_add_tail(&rblk_extent->list, &fbd->fbd_reloc_list);
-
-	return 0;
-}
-
-void ploop_fb_lost_range_init(struct ploop_freeblks_desc *fbd,
-			      iblock_t first_lost_iblk)
-{
-	fbd->fbd_first_lost_iblk = first_lost_iblk;
-	fbd->fbd_lost_range_len = 0;
-}
-
-void ploop_fb_relocation_start(struct ploop_freeblks_desc *fbd,
-			       __u32 n_scanned)
-{
-	iblock_t a_h = fbd->fbd_first_lost_iblk;
-	iblock_t new_a_h; /* where a_h will be after relocation
-			     if no WRITEs intervene */
-	struct ploop_relocblks_extent *r_extent;
-	struct ploop_relocblks_extent *r_extent_first;
-	int n_free = fbd->fbd_n_free;
-	u32 l;
-	struct ploop_freeblks_extent *fextent;
-
-	BUG_ON(fbd->fbd_lost_range_len != 0);
-	if (list_empty(&fbd->fbd_reloc_list)) {
-		fbd->fbd_first_lost_iblk -= n_scanned;
-		fbd->fbd_lost_range_len	 += n_scanned;
-		return;
-	}
-
-	r_extent_first = list_entry(fbd->fbd_reloc_list.next,
-				    struct ploop_relocblks_extent, list);
-	r_extent = list_entry(fbd->fbd_reloc_list.prev,
-			      struct ploop_relocblks_extent, list);
-	new_a_h = r_extent->iblk + r_extent->len;
-
-	BUG_ON(fbd->fbd_first_lost_iblk < new_a_h);
-	fbd->fbd_lost_range_len = fbd->fbd_first_lost_iblk - new_a_h;
-	fbd->fbd_first_lost_iblk = new_a_h;
-
-	if (!n_free)
-		return;
-
-	while (1) {
-		l = MIN(n_free, r_extent->len);
-
-		n_free	-= l;
-		new_a_h -= l;
-
-		if (!n_free)
-			break;
-
-		if (r_extent->list.prev == &fbd->fbd_reloc_list) {
-			r_extent = NULL;
-			break;
-		} else {
-			r_extent = list_entry(r_extent->list.prev,
-					      struct ploop_relocblks_extent,
-					      list);
-		}
-		/* skip lost blocks */
-		new_a_h = r_extent->iblk + r_extent->len;
-	}
-
-	l = 0;
-
-	/* ploop-balloon scanned exactly range [a_h - n_scanned .. a_h - 1] */
-	if (n_free) {
-		l = r_extent_first->iblk - (a_h - n_scanned);
-	} else if (r_extent->iblk == new_a_h) {
-		if (r_extent == r_extent_first) {
-			l = r_extent->iblk - (a_h - n_scanned);
-		} else {
-			struct ploop_relocblks_extent *r_extent_prev;
-
-			BUG_ON (r_extent->list.prev == &fbd->fbd_reloc_list);
-			r_extent_prev = list_entry(r_extent->list.prev,
-						   struct ploop_relocblks_extent,
-						   list);
-			l = r_extent->iblk - (r_extent_prev->iblk +
-					      r_extent_prev->len);
-		}
-	}
-
-	new_a_h -= l;
-
-	/* let's trim reloc_list a bit based on new_a_h */
-	while (r_extent_first->iblk < new_a_h) {
-
-		if (r_extent_first->iblk + r_extent_first->len > new_a_h) {
-			l = new_a_h - r_extent_first->iblk;
-			r_extent_first->iblk += l;
-			r_extent_first->clu  += l;
-			r_extent_first->len  -= l;
-			break;
-		}
-
-		if (r_extent_first->list.next == &fbd->fbd_reloc_list) {
-			list_del(&r_extent_first->list);
-			kfree(r_extent_first);
-			break;
-		}
-
-		list_del(&r_extent_first->list);
-		kfree(r_extent_first);
-		r_extent_first = list_entry(fbd->fbd_reloc_list.next,
-					    struct ploop_relocblks_extent,
-					    list);
-	}
-
-	if (!list_empty(&fbd->fbd_reloc_list)) {
-		fbd->fbd_lrb.ext = list_entry(fbd->fbd_reloc_list.prev,
-					      struct ploop_relocblks_extent,
-					      list);
-		fbd->fbd_lrb.off = fbd->fbd_lrb.ext->len - 1;
-
-		fbd->fbd_lost_range_addon = r_extent_first->iblk - new_a_h;
-	}
-
-	/* new_a_h is calculated. now, let's find "last free block" position */
-	if (ffb_iblk(fbd) < new_a_h) {
-		list_for_each_entry_reverse(fextent, &fbd->fbd_free_list, list)
-			if (fextent->iblk < new_a_h)
-				break;
-
-		BUG_ON(&fextent->list == &fbd->fbd_free_list);
-	} else
-		fextent = NULL;
-
-	fbd->fbd_lfb.ext = fextent; /* NULL means
-				       "no free blocks for relocation" */
-	if (fextent != NULL)
-		fbd->fbd_lfb.off = MIN(new_a_h - fextent->iblk,
-				       fextent->len) - 1;
-}
-
-int ploop_discard_add_bio(struct ploop_freeblks_desc *fbd, struct bio *bio)
-{
-	struct ploop_device *plo;
-
-	if (!fbd)
-		return -EOPNOTSUPP;
-
-	plo = fbd->plo;
-
-	if (!test_bit(PLOOP_S_DISCARD, &plo->state))
-		return -EOPNOTSUPP;
-	if (fbd->plo->maintenance_type != PLOOP_MNTN_DISCARD)
-		return -EBUSY;
-	/* only one request can be processed simultaneously */
-	if (fbd->fbd_dbl.head)
-		return -EBUSY;
-
-	fbd->fbd_dbl.head = fbd->fbd_dbl.tail = bio;
-
-	return 0;
-}
-
-int ploop_discard_is_inprogress(struct ploop_freeblks_desc *fbd)
-{
-	return fbd && fbd->fbd_dbl.head != NULL;
-}
diff --git a/drivers/block/ploop/freeblks.h b/drivers/block/ploop/freeblks.h
deleted file mode 100644
index b37f23e3d6b0..000000000000
--- a/drivers/block/ploop/freeblks.h
+++ /dev/null
@@ -1,58 +0,0 @@ 
-/*
- *  drivers/block/ploop/freeblks.h
- *
- *  Copyright (c) 2010-2015 Parallels IP Holdings GmbH
- *
- */
-
-#ifndef __FREEBLKS_H__
-#define __FREEBLKS_H__
-
-/* freeblks API - in-kernel balloon support */
-
-/* init/fini stuff */
-struct ploop_freeblks_desc *ploop_fb_init(struct ploop_device *plo);
-void ploop_fb_fini(struct ploop_freeblks_desc *fbd, int err);
-void ploop_fb_reinit(struct ploop_freeblks_desc *fbd, int err);
-int ploop_fb_add_free_extent(struct ploop_freeblks_desc *fbd, cluster_t clu, iblock_t iblk, u32 len);
-int ploop_fb_add_reloc_extent(struct ploop_freeblks_desc *fbd, cluster_t clu, iblock_t iblk, u32 len, u32 free);
-void ploop_fb_lost_range_init(struct ploop_freeblks_desc *fbd, iblock_t first_lost_iblk);
-void ploop_fb_relocation_start(struct ploop_freeblks_desc *fbd, __u32 n_scanned);
-int ploop_discard_add_bio(struct ploop_freeblks_desc *fbd, struct bio *bio);
-int ploop_discard_is_inprogress(struct ploop_freeblks_desc *fbd);
-
-/* avoid direct access to freeblks internals */
-int ploop_fb_get_n_relocated(struct ploop_freeblks_desc *fbd);
-int ploop_fb_get_n_relocating(struct ploop_freeblks_desc *fbd);
-int ploop_fb_get_n_free(struct ploop_freeblks_desc *fbd);
-iblock_t ploop_fb_get_alloc_head(struct ploop_freeblks_desc *fbd);
-int ploop_fb_get_lost_range_len(struct ploop_freeblks_desc *fbd);
-iblock_t ploop_fb_get_first_lost_iblk(struct ploop_freeblks_desc *fbd);
-
-/* get/set freezed level (for sanity checks) */
-int ploop_fb_get_freezed_level(struct ploop_freeblks_desc *fbd);
-void ploop_fb_set_freezed_level(struct ploop_freeblks_desc *fbd, int level);
-
-/* maintain rb-tree of "in progress" relocation requests */
-void ploop_fb_add_reloc_req(struct ploop_freeblks_desc *fbd, struct ploop_request *preq);
-void ploop_fb_del_reloc_req(struct ploop_freeblks_desc *fbd, struct ploop_request *preq);
-int ploop_fb_check_reloc_req(struct ploop_freeblks_desc *fbd, struct ploop_request *preq, unsigned long pin_state);
-
-/* helper for ioctl(PLOOP_IOC_FBGET) */
-int ploop_fb_copy_freeblks_to_user(struct ploop_freeblks_desc *fbd, void *arg,
-				   struct ploop_freeblks_ctl *ctl);
-int ploop_fb_filter_freeblks(struct ploop_freeblks_desc *fbd, unsigned long minlen);
-
-/* get/put "zero index" request */
-struct ploop_request *ploop_fb_get_zero_request(struct ploop_freeblks_desc *fbd);
-void ploop_fb_put_zero_request(struct ploop_freeblks_desc *fbd, struct ploop_request *preq);
-
-/* get/put block to relocate */
-int ploop_fb_get_reloc_block(struct ploop_freeblks_desc *fbd, cluster_t *from_clu, iblock_t *from_iblk,
-			     cluster_t *to_clu, iblock_t *to_iblk, u32 *free);
-void ploop_fb_relocate_req_completed(struct ploop_freeblks_desc *fbd);
-
-/* get free block to reuse */
-int ploop_fb_get_free_block(struct ploop_freeblks_desc *fbd, cluster_t *clu, iblock_t *iblk);
-
-#endif
diff --git a/include/linux/ploop/ploop.h b/include/linux/ploop/ploop.h
index ea6df68634a5..d37d1994434a 100644
--- a/include/linux/ploop/ploop.h
+++ b/include/linux/ploop/ploop.h
@@ -53,8 +53,8 @@  enum {
 				 * consumed by userspace yet */
 	PLOOP_S_CONGESTED,	/* Too many bios submitted to us */
 	PLOOP_S_NO_FALLOC_DISCARD, /* FIXME: Remove this: Unable to handle discard requests by fallocate */
-	PLOOP_S_DISCARD,	/* ploop is ready to handle discard request */
-	PLOOP_S_DISCARD_LOADED,	/* A discard request was handled and
+	PLOOP_S_DISCARD,	/* Obsolete: ploop is ready to handle discard request */
+	PLOOP_S_DISCARD_LOADED,	/* Obsolete: A discard request was handled and
 				   free blocks loaded */
 	PLOOP_S_LOCKED,	        /* ploop is locked by userspace
 				   (for minor mgmt only) */
@@ -471,7 +471,6 @@  struct ploop_device
 	struct ploop_stats	st;
 	char                    cookie[PLOOP_COOKIE_SIZE];
 
-	struct ploop_freeblks_desc *fbd;
 	struct ploop_pushbackup_desc *pbd;
 	struct block_device *dm_crypt_bdev;
 
@@ -490,10 +489,10 @@  enum
 	PLOOP_REQ_TRANS,
 	PLOOP_REQ_MERGE,
 	PLOOP_REQ_RELOC_A,	/* 'A' stands for allocate() */
-	PLOOP_REQ_RELOC_S,	/* 'S' stands for submit() */
+	PLOOP_REQ_RELOC_S,	/* Obsolete: 'S' stands for submit() */
 	PLOOP_REQ_RELOC_N,	/* 'N' stands for "nullify" */
-	PLOOP_REQ_ZERO,
-	PLOOP_REQ_DISCARD,
+	PLOOP_REQ_ZERO,		/* Obsolete */
+	PLOOP_REQ_DISCARD,	/* Obsolete */
 	PLOOP_REQ_RSYNC,
 	PLOOP_REQ_KAIO_FSYNC,	/*force image fsync by KAIO module */
 	PLOOP_REQ_POST_SUBMIT, /* preq needs post_submit processing */
@@ -505,10 +504,10 @@  enum
 
 #define PLOOP_REQ_MERGE_FL (1 << PLOOP_REQ_MERGE)
 #define PLOOP_REQ_RELOC_A_FL (1 << PLOOP_REQ_RELOC_A)
-#define PLOOP_REQ_RELOC_S_FL (1 << PLOOP_REQ_RELOC_S)
+#define PLOOP_REQ_RELOC_S_FL (1 << PLOOP_REQ_RELOC_S) /* Obsolete */
 #define PLOOP_REQ_RELOC_N_FL (1 << PLOOP_REQ_RELOC_N)
-#define PLOOP_REQ_DISCARD_FL (1 << PLOOP_REQ_DISCARD)
-#define PLOOP_REQ_ZERO_FL (1 << PLOOP_REQ_ZERO)
+#define PLOOP_REQ_DISCARD_FL (1 << PLOOP_REQ_DISCARD)	/* Obsolete */
+#define PLOOP_REQ_ZERO_FL (1 << PLOOP_REQ_ZERO)		/* Obsolete */
 
 enum
 {
@@ -927,8 +926,6 @@  extern struct kobj_type ploop_delta_ktype;
 void ploop_sysfs_init(struct ploop_device * plo);
 void ploop_sysfs_uninit(struct ploop_device * plo);
 
-void ploop_queue_zero_request(struct ploop_device *plo, struct ploop_request *orig_preq, cluster_t clu);
-
 int ploop_maintenance_wait(struct ploop_device * plo);
 
 extern int max_map_pages;
diff --git a/include/linux/ploop/ploop_if.h b/include/linux/ploop/ploop_if.h
index 3b5928cfb69e..f2a1e8ab4c70 100644
--- a/include/linux/ploop/ploop_if.h
+++ b/include/linux/ploop/ploop_if.h
@@ -234,14 +234,14 @@  enum {
 	PLOOP_MNTN_SNAPSHOT, /* bdev is freezed due to snapshot */
 
 	PLOOP_MNTN_TRACK,    /* tracking is in progress */
-	PLOOP_MNTN_DISCARD,  /* ready to handle discard requests */
+	PLOOP_MNTN_DISCARD,  /* Obsolete: ready to handle discard requests */
 
 	PLOOP_MNTN_NOFAST = 256,
 	/* all types below requires fast-path disabled ! */
 
 	PLOOP_MNTN_MERGE,    /* merge is in progress */
 	PLOOP_MNTN_GROW,     /* grow is in progress */
-	PLOOP_MNTN_RELOC,    /* relocation is in progress */
+	PLOOP_MNTN_RELOC,    /* Obsolete: relocation is in progress */
 	PLOOP_MNTN_PUSH_BACKUP, /* push backup is in progress */
 };
 
@@ -317,32 +317,32 @@  struct ploop_track_extent
 /* Increase size of block device */
 #define PLOOP_IOC_GROW		_IOW(PLOOPCTLTYPE, 17, struct ploop_ctl)
 
-/* Inquire current state of free block extents */
+/* Obsolete: Inquire current state of free block extents */
 #define PLOOP_IOC_FBGET		_IOW(PLOOPCTLTYPE, 18, struct ploop_freeblks_ctl)
 
 /* Start balloning or inquire maintenance_type or flush stale BALLON state */
 #define PLOOP_IOC_BALLOON	_IOW(PLOOPCTLTYPE, 19, struct ploop_balloon_ctl)
 
-/* Load free blocks to ploop */
+/* Obsolete: Load free blocks to ploop */
 #define PLOOP_IOC_FREEBLKS      _IOW(PLOOPCTLTYPE, 20, struct ploop_freeblks_ctl)
 
-/* Load blocks to relocate and initiate relocation process */
+/* Obsolete: Load blocks to relocate and initiate relocation process */
 #define PLOOP_IOC_RELOCBLKS     _IOW(PLOOPCTLTYPE, 21, struct ploop_relocblks_ctl)
 
 /* Search ploop_device global tree for first unused minor number */
 #define PLOOP_IOC_GETDEVICE    _IOW(PLOOPCTLTYPE, 22, struct ploop_getdevice_ctl)
 
-/* Start handling discard requests */
+/* Obsolete: Start handling discard requests */
 #define PLOOP_IOC_DISCARD_INIT _IO(PLOOPCTLTYPE, 23)
-/* Stop handling discard requests */
+/* Obsolete: Stop handling discard requests */
 #define PLOOP_IOC_DISCARD_FINI _IO(PLOOPCTLTYPE, 24)
-/* Wait a discard request */
+/* Obsolete: Wait a discard request */
 #define PLOOP_IOC_DISCARD_WAIT _IO(PLOOPCTLTYPE, 25)
 
-/* Drop current state of free block extents */
+/* Obsolete: Drop current state of free block extents */
 #define PLOOP_IOC_FBDROP	_IO(PLOOPCTLTYPE, 26)
 
-/* Filter extents with sizes less than arg */
+/* Obsolete: Filter extents with sizes less than arg */
 #define PLOOP_IOC_FBFILTER	_IOR(PLOOPCTLTYPE, 27, unsigned long)
 
 /* Set maximum size for the top delta . */