1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * RDMA Network Block Driver 4 * 5 * Copyright (c) 2014 - 2018 ProfitBricks GmbH. All rights reserved. 6 * Copyright (c) 2018 - 2019 1&1 IONOS Cloud GmbH. All rights reserved. 7 * Copyright (c) 2019 - 2020 1&1 IONOS SE. All rights reserved. 8 */ 9#undef pr_fmt 10#define pr_fmt(fmt) KBUILD_MODNAME " L" __stringify(__LINE__) ": " fmt 11 12#include "rnbd-srv-dev.h" 13#include "rnbd-log.h" 14 15struct rnbd_dev *rnbd_dev_open(const char *path, fmode_t flags, 16 struct bio_set *bs) 17{ 18 struct rnbd_dev *dev; 19 int ret; 20 21 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 22 if (!dev) 23 return ERR_PTR(-ENOMEM); 24 25 dev->blk_open_flags = flags; 26 dev->bdev = blkdev_get_by_path(path, flags, THIS_MODULE); 27 ret = PTR_ERR_OR_ZERO(dev->bdev); 28 if (ret) 29 goto err; 30 31 dev->blk_open_flags = flags; 32 bdevname(dev->bdev, dev->name); 33 dev->ibd_bio_set = bs; 34 35 return dev; 36 37err: 38 kfree(dev); 39 return ERR_PTR(ret); 40} 41 42void rnbd_dev_close(struct rnbd_dev *dev) 43{ 44 blkdev_put(dev->bdev, dev->blk_open_flags); 45 kfree(dev); 46} 47 48void rnbd_dev_bi_end_io(struct bio *bio) 49{ 50 struct rnbd_dev_blk_io *io = bio->bi_private; 51 52 rnbd_endio(io->priv, blk_status_to_errno(bio->bi_status)); 53 bio_put(bio); 54} 55 56/** 57 * rnbd_bio_map_kern - map kernel address into bio 58 * @data: pointer to buffer to map 59 * @bs: bio_set to use. 60 * @len: length in bytes 61 * @gfp_mask: allocation flags for bio allocation 62 * 63 * Map the kernel address into a bio suitable for io to a block 64 * device. Returns an error pointer in case of error. 65 */ 66struct bio *rnbd_bio_map_kern(void *data, struct bio_set *bs, 67 unsigned int len, gfp_t gfp_mask) 68{ 69 unsigned long kaddr = (unsigned long)data; 70 unsigned long end = (kaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT; 71 unsigned long start = kaddr >> PAGE_SHIFT; 72 const int nr_pages = end - start; 73 int offset, i; 74 struct bio *bio; 75 76 bio = bio_alloc_bioset(gfp_mask, nr_pages, bs); 77 if (!bio) 78 return ERR_PTR(-ENOMEM); 79 80 offset = offset_in_page(kaddr); 81 for (i = 0; i < nr_pages; i++) { 82 unsigned int bytes = PAGE_SIZE - offset; 83 84 if (len <= 0) 85 break; 86 87 if (bytes > len) 88 bytes = len; 89 90 if (bio_add_page(bio, virt_to_page(data), bytes, 91 offset) < bytes) { 92 /* we don't support partial mappings */ 93 bio_put(bio); 94 return ERR_PTR(-EINVAL); 95 } 96 97 data += bytes; 98 len -= bytes; 99 offset = 0; 100 } 101 102 return bio; 103} 104