Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 43cade80 authored by Omar Sandoval's avatar Omar Sandoval Committed by Jens Axboe
Browse files

loop: fold loop_switch() into callers



The comments here are really outdated, and blk-mq made flushing much
simpler, so just fold the two cases into the callers.

Reviewed-by: default avatarMing Lei <ming.lei@redhat.com>
Reviewed-by: default avatarHannes Reinecke <hare@suse.com>
Signed-off-by: default avatarOmar Sandoval <osandov@fb.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 89e4fdec
Loading
Loading
Loading
Loading
+11 −65
Original line number Diff line number Diff line
@@ -546,72 +546,12 @@ static int do_req_filebacked(struct loop_device *lo, struct request *rq)
	}
}

struct switch_request {
	struct file *file;
	struct completion wait;
};

static inline void loop_update_dio(struct loop_device *lo)
{
	__loop_update_dio(lo, io_is_direct(lo->lo_backing_file) |
			lo->use_dio);
}

/*
 * Do the actual switch; called from the BIO completion routine
 */
static void do_loop_switch(struct loop_device *lo, struct switch_request *p)
{
	struct file *file = p->file;
	struct file *old_file = lo->lo_backing_file;
	struct address_space *mapping;

	/* if no new file, only flush of queued bios requested */
	if (!file)
		return;

	mapping = file->f_mapping;
	mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask);
	lo->lo_backing_file = file;
	lo->old_gfp_mask = mapping_gfp_mask(mapping);
	mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
	loop_update_dio(lo);
}

/*
 * loop_switch performs the hard work of switching a backing store.
 * First it needs to flush existing IO, it does this by sending a magic
 * BIO down the pipe. The completion of this BIO does the actual switch.
 */
static int loop_switch(struct loop_device *lo, struct file *file)
{
	struct switch_request w;

	w.file = file;

	/* freeze queue and wait for completion of scheduled requests */
	blk_mq_freeze_queue(lo->lo_queue);

	/* do the switch action */
	do_loop_switch(lo, &w);

	/* unfreeze */
	blk_mq_unfreeze_queue(lo->lo_queue);

	return 0;
}

/*
 * Helper to flush the IOs in loop, but keeping loop thread running
 */
static int loop_flush(struct loop_device *lo)
{
	/* loop not yet configured, no running thread, nothing to flush */
	if (lo->lo_state != Lo_bound)
		return 0;
	return loop_switch(lo, NULL);
}

static void loop_reread_partitions(struct loop_device *lo,
				   struct block_device *bdev)
{
@@ -676,9 +616,14 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
		goto out_putf;

	/* and ... switch */
	error = loop_switch(lo, file);
	if (error)
		goto out_putf;
	blk_mq_freeze_queue(lo->lo_queue);
	mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask);
	lo->lo_backing_file = file;
	lo->old_gfp_mask = mapping_gfp_mask(file->f_mapping);
	mapping_set_gfp_mask(file->f_mapping,
			     lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
	loop_update_dio(lo);
	blk_mq_unfreeze_queue(lo->lo_queue);

	fput(old_file);
	if (lo->lo_flags & LO_FLAGS_PARTSCAN)
@@ -1601,12 +1546,13 @@ static void lo_release(struct gendisk *disk, fmode_t mode)
		err = loop_clr_fd(lo);
		if (!err)
			return;
	} else {
	} else if (lo->lo_state == Lo_bound) {
		/*
		 * Otherwise keep thread (if running) and config,
		 * but flush possible ongoing bios in thread.
		 */
		loop_flush(lo);
		blk_mq_freeze_queue(lo->lo_queue);
		blk_mq_unfreeze_queue(lo->lo_queue);
	}

	mutex_unlock(&lo->lo_ctl_mutex);