2020-05-11 16:51:27 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* RDMA Network Block Driver
*
* Copyright ( c ) 2014 - 2018 ProfitBricks GmbH . All rights reserved .
* Copyright ( c ) 2018 - 2019 1 & 1 IONOS Cloud GmbH . All rights reserved .
* Copyright ( c ) 2019 - 2020 1 & 1 IONOS SE . All rights reserved .
*/
# undef pr_fmt
# define pr_fmt(fmt) KBUILD_MODNAME " L" __stringify(__LINE__) ": " fmt
# include "rnbd-srv-dev.h"
# include "rnbd-log.h"
struct rnbd_dev * rnbd_dev_open ( const char * path , fmode_t flags ,
struct bio_set * bs )
{
struct rnbd_dev * dev ;
int ret ;
dev = kzalloc ( sizeof ( * dev ) , GFP_KERNEL ) ;
if ( ! dev )
return ERR_PTR ( - ENOMEM ) ;
dev - > blk_open_flags = flags ;
dev - > bdev = blkdev_get_by_path ( path , flags , THIS_MODULE ) ;
ret = PTR_ERR_OR_ZERO ( dev - > bdev ) ;
if ( ret )
goto err ;
dev - > blk_open_flags = flags ;
bdevname ( dev - > bdev , dev - > name ) ;
dev - > ibd_bio_set = bs ;
return dev ;
err :
kfree ( dev ) ;
return ERR_PTR ( ret ) ;
}
void rnbd_dev_close ( struct rnbd_dev * dev )
{
blkdev_put ( dev - > bdev , dev - > blk_open_flags ) ;
kfree ( dev ) ;
}
2020-07-30 12:13:57 +03:00
void rnbd_dev_bi_end_io ( struct bio * bio )
2020-05-11 16:51:27 +03:00
{
struct rnbd_dev_blk_io * io = bio - > bi_private ;
rnbd_endio ( io - > priv , blk_status_to_errno ( bio - > bi_status ) ) ;
bio_put ( bio ) ;
}
/**
* rnbd_bio_map_kern - map kernel address into bio
* @ data : pointer to buffer to map
* @ bs : bio_set to use .
* @ len : length in bytes
* @ gfp_mask : allocation flags for bio allocation
*
* Map the kernel address into a bio suitable for io to a block
* device . Returns an error pointer in case of error .
*/
2020-07-30 12:13:57 +03:00
struct bio * rnbd_bio_map_kern ( void * data , struct bio_set * bs ,
unsigned int len , gfp_t gfp_mask )
2020-05-11 16:51:27 +03:00
{
unsigned long kaddr = ( unsigned long ) data ;
unsigned long end = ( kaddr + len + PAGE_SIZE - 1 ) > > PAGE_SHIFT ;
unsigned long start = kaddr > > PAGE_SHIFT ;
const int nr_pages = end - start ;
int offset , i ;
struct bio * bio ;
bio = bio_alloc_bioset ( gfp_mask , nr_pages , bs ) ;
if ( ! bio )
return ERR_PTR ( - ENOMEM ) ;
offset = offset_in_page ( kaddr ) ;
for ( i = 0 ; i < nr_pages ; i + + ) {
unsigned int bytes = PAGE_SIZE - offset ;
if ( len < = 0 )
break ;
if ( bytes > len )
bytes = len ;
if ( bio_add_page ( bio , virt_to_page ( data ) , bytes ,
offset ) < bytes ) {
/* we don't support partial mappings */
bio_put ( bio ) ;
return ERR_PTR ( - EINVAL ) ;
}
data + = bytes ;
len - = bytes ;
offset = 0 ;
}
return bio ;
}