Skip to content

Commit aa4d861

Browse files
Christoph HellwigAl Viro
authored andcommitted
block: loop: switch to VFS ITER_BVEC
Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
1 parent 6683de3 commit aa4d861

File tree

1 file changed

+120
-174
lines changed

1 file changed

+120
-174
lines changed

drivers/block/loop.c

Lines changed: 120 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -88,28 +88,6 @@ static int part_shift;
8888

8989
static struct workqueue_struct *loop_wq;
9090

91-
/*
92-
* Transfer functions
93-
*/
94-
static int transfer_none(struct loop_device *lo, int cmd,
95-
struct page *raw_page, unsigned raw_off,
96-
struct page *loop_page, unsigned loop_off,
97-
int size, sector_t real_block)
98-
{
99-
char *raw_buf = kmap_atomic(raw_page) + raw_off;
100-
char *loop_buf = kmap_atomic(loop_page) + loop_off;
101-
102-
if (cmd == READ)
103-
memcpy(loop_buf, raw_buf, size);
104-
else
105-
memcpy(raw_buf, loop_buf, size);
106-
107-
kunmap_atomic(loop_buf);
108-
kunmap_atomic(raw_buf);
109-
cond_resched();
110-
return 0;
111-
}
112-
11391
static int transfer_xor(struct loop_device *lo, int cmd,
11492
struct page *raw_page, unsigned raw_off,
11593
struct page *loop_page, unsigned loop_off,
@@ -148,14 +126,13 @@ static int xor_init(struct loop_device *lo, const struct loop_info64 *info)
148126

149127
static struct loop_func_table none_funcs = {
150128
.number = LO_CRYPT_NONE,
151-
.transfer = transfer_none,
152-
};
129+
};
153130

154131
static struct loop_func_table xor_funcs = {
155132
.number = LO_CRYPT_XOR,
156133
.transfer = transfer_xor,
157134
.init = xor_init
158-
};
135+
};
159136

160137
/* xfer_funcs[0] is special - its release function is never called */
161138
static struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = {
@@ -215,207 +192,169 @@ lo_do_transfer(struct loop_device *lo, int cmd,
215192
struct page *lpage, unsigned loffs,
216193
int size, sector_t rblock)
217194
{
218-
if (unlikely(!lo->transfer))
195+
int ret;
196+
197+
ret = lo->transfer(lo, cmd, rpage, roffs, lpage, loffs, size, rblock);
198+
if (likely(!ret))
219199
return 0;
220200

221-
return lo->transfer(lo, cmd, rpage, roffs, lpage, loffs, size, rblock);
201+
printk_ratelimited(KERN_ERR
202+
"loop: Transfer error at byte offset %llu, length %i.\n",
203+
(unsigned long long)rblock << 9, size);
204+
return ret;
222205
}
223206

224-
/**
225-
* __do_lo_send_write - helper for writing data to a loop device
226-
*
227-
* This helper just factors out common code between do_lo_send_direct_write()
228-
* and do_lo_send_write().
229-
*/
230-
static int __do_lo_send_write(struct file *file,
231-
u8 *buf, const int len, loff_t pos)
207+
static int lo_write_bvec(struct file *file, struct bio_vec *bvec, loff_t *ppos)
232208
{
233-
struct kvec kvec = {.iov_base = buf, .iov_len = len};
234-
struct iov_iter from;
209+
struct iov_iter i;
235210
ssize_t bw;
236211

237-
iov_iter_kvec(&from, ITER_KVEC | WRITE, &kvec, 1, len);
212+
iov_iter_bvec(&i, ITER_BVEC, bvec, 1, bvec->bv_len);
238213

239214
file_start_write(file);
240-
bw = vfs_iter_write(file, &from, &pos);
215+
bw = vfs_iter_write(file, &i, ppos);
241216
file_end_write(file);
242-
if (likely(bw == len))
217+
218+
if (likely(bw == bvec->bv_len))
243219
return 0;
244-
printk_ratelimited(KERN_ERR "loop: Write error at byte offset %llu, length %i.\n",
245-
(unsigned long long)pos, len);
220+
221+
printk_ratelimited(KERN_ERR
222+
"loop: Write error at byte offset %llu, length %i.\n",
223+
(unsigned long long)*ppos, bvec->bv_len);
246224
if (bw >= 0)
247225
bw = -EIO;
248226
return bw;
249227
}
250228

251-
/**
252-
* do_lo_send_direct_write - helper for writing data to a loop device
253-
*
254-
* This is the fast, non-transforming version that does not need double
255-
* buffering.
256-
*/
257-
static int do_lo_send_direct_write(struct loop_device *lo,
258-
struct bio_vec *bvec, loff_t pos, struct page *page)
229+
static int lo_write_simple(struct loop_device *lo, struct request *rq,
230+
loff_t pos)
259231
{
260-
ssize_t bw = __do_lo_send_write(lo->lo_backing_file,
261-
kmap(bvec->bv_page) + bvec->bv_offset,
262-
bvec->bv_len, pos);
263-
kunmap(bvec->bv_page);
264-
cond_resched();
265-
return bw;
232+
struct bio_vec bvec;
233+
struct req_iterator iter;
234+
int ret = 0;
235+
236+
rq_for_each_segment(bvec, rq, iter) {
237+
ret = lo_write_bvec(lo->lo_backing_file, &bvec, &pos);
238+
if (ret < 0)
239+
break;
240+
cond_resched();
241+
}
242+
243+
return ret;
266244
}
267245

268-
/**
269-
* do_lo_send_write - helper for writing data to a loop device
270-
*
246+
/*
271247
* This is the slow, transforming version that needs to double buffer the
272248
* data as it cannot do the transformations in place without having direct
273249
* access to the destination pages of the backing file.
274250
*/
275-
static int do_lo_send_write(struct loop_device *lo, struct bio_vec *bvec,
276-
loff_t pos, struct page *page)
251+
static int lo_write_transfer(struct loop_device *lo, struct request *rq,
252+
loff_t pos)
277253
{
278-
int ret = lo_do_transfer(lo, WRITE, page, 0, bvec->bv_page,
279-
bvec->bv_offset, bvec->bv_len, pos >> 9);
280-
if (likely(!ret))
281-
return __do_lo_send_write(lo->lo_backing_file,
282-
page_address(page), bvec->bv_len,
283-
pos);
284-
printk_ratelimited(KERN_ERR "loop: Transfer error at byte offset %llu, "
285-
"length %i.\n", (unsigned long long)pos, bvec->bv_len);
286-
if (ret > 0)
287-
ret = -EIO;
288-
return ret;
289-
}
290-
291-
static int lo_send(struct loop_device *lo, struct request *rq, loff_t pos)
292-
{
293-
int (*do_lo_send)(struct loop_device *, struct bio_vec *, loff_t,
294-
struct page *page);
295-
struct bio_vec bvec;
254+
struct bio_vec bvec, b;
296255
struct req_iterator iter;
297-
struct page *page = NULL;
256+
struct page *page;
298257
int ret = 0;
299258

300-
if (lo->transfer != transfer_none) {
301-
page = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
302-
if (unlikely(!page))
303-
goto fail;
304-
kmap(page);
305-
do_lo_send = do_lo_send_write;
306-
} else {
307-
do_lo_send = do_lo_send_direct_write;
308-
}
259+
page = alloc_page(GFP_NOIO);
260+
if (unlikely(!page))
261+
return -ENOMEM;
309262

310263
rq_for_each_segment(bvec, rq, iter) {
311-
ret = do_lo_send(lo, &bvec, pos, page);
264+
ret = lo_do_transfer(lo, WRITE, page, 0, bvec.bv_page,
265+
bvec.bv_offset, bvec.bv_len, pos >> 9);
266+
if (unlikely(ret))
267+
break;
268+
269+
b.bv_page = page;
270+
b.bv_offset = 0;
271+
b.bv_len = bvec.bv_len;
272+
ret = lo_write_bvec(lo->lo_backing_file, &b, &pos);
312273
if (ret < 0)
313274
break;
314-
pos += bvec.bv_len;
315275
}
316-
if (page) {
317-
kunmap(page);
318-
__free_page(page);
319-
}
320-
out:
276+
277+
__free_page(page);
321278
return ret;
322-
fail:
323-
printk_ratelimited(KERN_ERR "loop: Failed to allocate temporary page for write.\n");
324-
ret = -ENOMEM;
325-
goto out;
326279
}
327280

328-
struct lo_read_data {
329-
struct loop_device *lo;
330-
struct page *page;
331-
unsigned offset;
332-
int bsize;
333-
};
281+
static int lo_read_simple(struct loop_device *lo, struct request *rq,
282+
loff_t pos)
283+
{
284+
struct bio_vec bvec;
285+
struct req_iterator iter;
286+
struct iov_iter i;
287+
ssize_t len;
334288

335-
static int
336-
lo_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
337-
struct splice_desc *sd)
338-
{
339-
struct lo_read_data *p = sd->u.data;
340-
struct loop_device *lo = p->lo;
341-
struct page *page = buf->page;
342-
sector_t IV;
343-
int size;
344-
345-
IV = ((sector_t) page->index << (PAGE_CACHE_SHIFT - 9)) +
346-
(buf->offset >> 9);
347-
size = sd->len;
348-
if (size > p->bsize)
349-
size = p->bsize;
350-
351-
if (lo_do_transfer(lo, READ, page, buf->offset, p->page, p->offset, size, IV)) {
352-
printk_ratelimited(KERN_ERR "loop: transfer error block %ld\n",
353-
page->index);
354-
size = -EINVAL;
355-
}
289+
rq_for_each_segment(bvec, rq, iter) {
290+
iov_iter_bvec(&i, ITER_BVEC, &bvec, 1, bvec.bv_len);
291+
len = vfs_iter_read(lo->lo_backing_file, &i, &pos);
292+
if (len < 0)
293+
return len;
356294

357-
flush_dcache_page(p->page);
295+
flush_dcache_page(bvec.bv_page);
358296

359-
if (size > 0)
360-
p->offset += size;
297+
if (len != bvec.bv_len) {
298+
struct bio *bio;
361299

362-
return size;
363-
}
300+
__rq_for_each_bio(bio, rq)
301+
zero_fill_bio(bio);
302+
break;
303+
}
304+
cond_resched();
305+
}
364306

365-
static int
366-
lo_direct_splice_actor(struct pipe_inode_info *pipe, struct splice_desc *sd)
367-
{
368-
return __splice_from_pipe(pipe, sd, lo_splice_actor);
307+
return 0;
369308
}
370309

371-
static ssize_t
372-
do_lo_receive(struct loop_device *lo,
373-
struct bio_vec *bvec, int bsize, loff_t pos)
310+
static int lo_read_transfer(struct loop_device *lo, struct request *rq,
311+
loff_t pos)
374312
{
375-
struct lo_read_data cookie;
376-
struct splice_desc sd;
377-
struct file *file;
378-
ssize_t retval;
313+
struct bio_vec bvec, b;
314+
struct req_iterator iter;
315+
struct iov_iter i;
316+
struct page *page;
317+
ssize_t len;
318+
int ret = 0;
379319

380-
cookie.lo = lo;
381-
cookie.page = bvec->bv_page;
382-
cookie.offset = bvec->bv_offset;
383-
cookie.bsize = bsize;
320+
page = alloc_page(GFP_NOIO);
321+
if (unlikely(!page))
322+
return -ENOMEM;
384323

385-
sd.len = 0;
386-
sd.total_len = bvec->bv_len;
387-
sd.flags = 0;
388-
sd.pos = pos;
389-
sd.u.data = &cookie;
324+
rq_for_each_segment(bvec, rq, iter) {
325+
loff_t offset = pos;
390326

391-
file = lo->lo_backing_file;
392-
retval = splice_direct_to_actor(file, &sd, lo_direct_splice_actor);
327+
b.bv_page = page;
328+
b.bv_offset = 0;
329+
b.bv_len = bvec.bv_len;
393330

394-
return retval;
395-
}
331+
iov_iter_bvec(&i, ITER_BVEC, &b, 1, b.bv_len);
332+
len = vfs_iter_read(lo->lo_backing_file, &i, &pos);
333+
if (len < 0) {
334+
ret = len;
335+
goto out_free_page;
336+
}
396337

397-
static int
398-
lo_receive(struct loop_device *lo, struct request *rq, int bsize, loff_t pos)
399-
{
400-
struct bio_vec bvec;
401-
struct req_iterator iter;
402-
ssize_t s;
338+
ret = lo_do_transfer(lo, READ, page, 0, bvec.bv_page,
339+
bvec.bv_offset, len, offset >> 9);
340+
if (ret)
341+
goto out_free_page;
403342

404-
rq_for_each_segment(bvec, rq, iter) {
405-
s = do_lo_receive(lo, &bvec, bsize, pos);
406-
if (s < 0)
407-
return s;
343+
flush_dcache_page(bvec.bv_page);
408344

409-
if (s != bvec.bv_len) {
345+
if (len != bvec.bv_len) {
410346
struct bio *bio;
411347

412348
__rq_for_each_bio(bio, rq)
413349
zero_fill_bio(bio);
414350
break;
415351
}
416-
pos += bvec.bv_len;
417352
}
418-
return 0;
353+
354+
ret = 0;
355+
out_free_page:
356+
__free_page(page);
357+
return ret;
419358
}
420359

421360
static int lo_discard(struct loop_device *lo, struct request *rq, loff_t pos)
@@ -464,10 +403,17 @@ static int do_req_filebacked(struct loop_device *lo, struct request *rq)
464403
ret = lo_req_flush(lo, rq);
465404
else if (rq->cmd_flags & REQ_DISCARD)
466405
ret = lo_discard(lo, rq, pos);
406+
else if (lo->transfer)
407+
ret = lo_write_transfer(lo, rq, pos);
467408
else
468-
ret = lo_send(lo, rq, pos);
469-
} else
470-
ret = lo_receive(lo, rq, lo->lo_blocksize, pos);
409+
ret = lo_write_simple(lo, rq, pos);
410+
411+
} else {
412+
if (lo->transfer)
413+
ret = lo_read_transfer(lo, rq, pos);
414+
else
415+
ret = lo_read_simple(lo, rq, pos);
416+
}
471417

472418
return ret;
473419
}
@@ -788,7 +734,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
788734
lo->lo_device = bdev;
789735
lo->lo_flags = lo_flags;
790736
lo->lo_backing_file = file;
791-
lo->transfer = transfer_none;
737+
lo->transfer = NULL;
792738
lo->ioctl = NULL;
793739
lo->lo_sizelimit = 0;
794740
lo->old_gfp_mask = mapping_gfp_mask(mapping);
@@ -1007,7 +953,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
1007953
memcpy(lo->lo_encrypt_key, info->lo_encrypt_key,
1008954
info->lo_encrypt_key_size);
1009955
lo->lo_key_owner = uid;
1010-
}
956+
}
1011957

1012958
return 0;
1013959
}

0 commit comments

Comments
 (0)