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

Commit cf655d95 authored by Ming Lei's avatar Ming Lei Committed by Jens Axboe
Browse files

block: loop: introduce lo_discard() and lo_req_flush()



No behaviour change, just move the handling for REQ_DISCARD
and REQ_FLUSH in these two functions.

Signed-off-by: default avatarMing Lei <ming.lei@canonical.com>
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent 30112013
Loading
Loading
Loading
Loading
+40 −33
Original line number Diff line number Diff line
@@ -417,54 +417,61 @@ lo_receive(struct loop_device *lo, struct request *rq, int bsize, loff_t pos)
	return 0;
}

static int do_req_filebacked(struct loop_device *lo, struct request *rq)
static int lo_discard(struct loop_device *lo, struct request *rq, loff_t pos)
{
	loff_t pos;
	int ret;

	pos = ((loff_t) blk_rq_pos(rq) << 9) + lo->lo_offset;

	if (rq->cmd_flags & REQ_WRITE) {
		struct file *file = lo->lo_backing_file;

		if (rq->cmd_flags & REQ_FLUSH) {
			ret = vfs_fsync(file, 0);
			if (unlikely(ret && ret != -EINVAL)) {
				ret = -EIO;
				goto out;
			}
		}

	/*
	 * We use punch hole to reclaim the free space used by the
	 * image a.k.a. discard. However we do not support discard if
	 * encryption is enabled, because it may give an attacker
	 * useful information.
	 */
		if (rq->cmd_flags & REQ_DISCARD) {
	struct file *file = lo->lo_backing_file;
	int mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
	int ret;

			if ((!file->f_op->fallocate) ||
			    lo->lo_encrypt_key_size) {
	if ((!file->f_op->fallocate) || lo->lo_encrypt_key_size) {
		ret = -EOPNOTSUPP;
		goto out;
	}
			ret = file->f_op->fallocate(file, mode, pos,
						    blk_rq_bytes(rq));
			if (unlikely(ret && ret != -EINVAL &&
				     ret != -EOPNOTSUPP))

	ret = file->f_op->fallocate(file, mode, pos, blk_rq_bytes(rq));
	if (unlikely(ret && ret != -EINVAL && ret != -EOPNOTSUPP))
		ret = -EIO;
			goto out;
 out:
	return ret;
}

		ret = lo_send(lo, rq, pos);

		if ((rq->cmd_flags & REQ_FUA) && !ret) {
			ret = vfs_fsync(file, 0);
static int lo_req_flush(struct loop_device *lo, struct request *rq)
{
	struct file *file = lo->lo_backing_file;
	int ret = vfs_fsync(file, 0);
	if (unlikely(ret && ret != -EINVAL))
		ret = -EIO;

	return ret;
}

static int do_req_filebacked(struct loop_device *lo, struct request *rq)
{
	loff_t pos;
	int ret;

	pos = ((loff_t) blk_rq_pos(rq) << 9) + lo->lo_offset;

	if (rq->cmd_flags & REQ_WRITE) {

		if (rq->cmd_flags & REQ_FLUSH)
			ret = lo_req_flush(lo, rq);

		if (rq->cmd_flags & REQ_DISCARD) {
			ret = lo_discard(lo, rq, pos);
			goto out;
		}

		ret = lo_send(lo, rq, pos);

		if ((rq->cmd_flags & REQ_FUA) && !ret)
			ret = lo_req_flush(lo, rq);
	} else
		ret = lo_receive(lo, rq, lo->lo_blocksize, pos);