mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git
synced 2026-05-02 18:17:50 -04:00
Merge tag 'for-5.16/drivers-2021-10-29' of git://git.kernel.dk/linux-block
Pull block driver updates from Jens Axboe:
- paride driver cleanups (Christoph)
- Remove cryptoloop support (Christoph)
- null_blk poll support (me)
- Now that add_disk() supports proper error handling, add it to various
drivers (Luis)
- Make ataflop actually work again (Michael)
- s390 dasd fixes (Stefan, Heiko)
- nbd fixes (Yu, Ye)
- Remove redundant wq flush in mtip32xx (Christophe)
- NVMe updates
- fix a multipath partition scanning deadlock (Hannes Reinecke)
- generate uevent once a multipath namespace is operational again
(Hannes Reinecke)
- support unique discovery controller NQNs (Hannes Reinecke)
- fix use-after-free when a port is removed (Israel Rukshin)
- clear shadow doorbell memory on resets (Keith Busch)
- use struct_size (Len Baker)
- add error handling support for add_disk (Luis Chamberlain)
- limit the maximal queue size for RDMA controllers (Max Gurtovoy)
- use a few more symbolic names (Max Gurtovoy)
- fix error code in nvme_rdma_setup_ctrl (Max Gurtovoy)
- add support for ->map_queues on FC (Saurav Kashyap)
- support the current discovery subsystem entry (Hannes Reinecke)
- use flex_array_size and struct_size (Len Baker)
- bcache fixes (Christoph, Coly, Chao, Lin, Qing)
- MD updates (Christoph, Guoqing, Xiao)
- Misc fixes (Dan, Ding, Jiapeng, Shin'ichiro, Ye)
* tag 'for-5.16/drivers-2021-10-29' of git://git.kernel.dk/linux-block: (117 commits)
null_blk: Fix handling of submit_queues and poll_queues attributes
block: ataflop: Fix warning comparing pointer to 0
bcache: replace snprintf in show functions with sysfs_emit
bcache: move uapi header bcache.h to bcache code directory
nvmet: use flex_array_size and struct_size
nvmet: register discovery subsystem as 'current'
nvmet: switch check for subsystem type
nvme: add new discovery log page entry definitions
block: ataflop: more blk-mq refactoring fixes
block: remove support for cryptoloop and the xor transfer
mtd: add add_disk() error handling
rnbd: add error handling support for add_disk()
um/drivers/ubd_kern: add error handling support for add_disk()
m68k/emu/nfblock: add error handling support for add_disk()
xen-blkfront: add error handling support for add_disk()
bcache: add error handling support for add_disk()
dm: add add_disk() error handling
block: aoe: fixup coccinelle warnings
nvmet: use struct_size over open coded arithmetic
nvme: drop scan_lock and always kick requeue list when removing namespaces
...
This commit is contained in:
@@ -133,58 +133,6 @@ static void loop_global_unlock(struct loop_device *lo, bool global)
|
||||
static int max_part;
|
||||
static int part_shift;
|
||||
|
||||
static int transfer_xor(struct loop_device *lo, int cmd,
|
||||
struct page *raw_page, unsigned raw_off,
|
||||
struct page *loop_page, unsigned loop_off,
|
||||
int size, sector_t real_block)
|
||||
{
|
||||
char *raw_buf = kmap_atomic(raw_page) + raw_off;
|
||||
char *loop_buf = kmap_atomic(loop_page) + loop_off;
|
||||
char *in, *out, *key;
|
||||
int i, keysize;
|
||||
|
||||
if (cmd == READ) {
|
||||
in = raw_buf;
|
||||
out = loop_buf;
|
||||
} else {
|
||||
in = loop_buf;
|
||||
out = raw_buf;
|
||||
}
|
||||
|
||||
key = lo->lo_encrypt_key;
|
||||
keysize = lo->lo_encrypt_key_size;
|
||||
for (i = 0; i < size; i++)
|
||||
*out++ = *in++ ^ key[(i & 511) % keysize];
|
||||
|
||||
kunmap_atomic(loop_buf);
|
||||
kunmap_atomic(raw_buf);
|
||||
cond_resched();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xor_init(struct loop_device *lo, const struct loop_info64 *info)
|
||||
{
|
||||
if (unlikely(info->lo_encrypt_key_size <= 0))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct loop_func_table none_funcs = {
|
||||
.number = LO_CRYPT_NONE,
|
||||
};
|
||||
|
||||
static struct loop_func_table xor_funcs = {
|
||||
.number = LO_CRYPT_XOR,
|
||||
.transfer = transfer_xor,
|
||||
.init = xor_init
|
||||
};
|
||||
|
||||
/* xfer_funcs[0] is special - its release function is never called */
|
||||
static struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = {
|
||||
&none_funcs,
|
||||
&xor_funcs
|
||||
};
|
||||
|
||||
static loff_t get_size(loff_t offset, loff_t sizelimit, struct file *file)
|
||||
{
|
||||
loff_t loopsize;
|
||||
@@ -228,8 +176,7 @@ static void __loop_update_dio(struct loop_device *lo, bool dio)
|
||||
/*
|
||||
* We support direct I/O only if lo_offset is aligned with the
|
||||
* logical I/O size of backing device, and the logical block
|
||||
* size of loop is bigger than the backing device's and the loop
|
||||
* needn't transform transfer.
|
||||
* size of loop is bigger than the backing device's.
|
||||
*
|
||||
* TODO: the above condition may be loosed in the future, and
|
||||
* direct I/O may be switched runtime at that time because most
|
||||
@@ -238,8 +185,7 @@ static void __loop_update_dio(struct loop_device *lo, bool dio)
|
||||
if (dio) {
|
||||
if (queue_logical_block_size(lo->lo_queue) >= sb_bsize &&
|
||||
!(lo->lo_offset & dio_align) &&
|
||||
mapping->a_ops->direct_IO &&
|
||||
!lo->transfer)
|
||||
mapping->a_ops->direct_IO)
|
||||
use_dio = true;
|
||||
else
|
||||
use_dio = false;
|
||||
@@ -286,24 +232,6 @@ static void loop_set_size(struct loop_device *lo, loff_t size)
|
||||
kobject_uevent(&disk_to_dev(lo->lo_disk)->kobj, KOBJ_CHANGE);
|
||||
}
|
||||
|
||||
static inline int
|
||||
lo_do_transfer(struct loop_device *lo, int cmd,
|
||||
struct page *rpage, unsigned roffs,
|
||||
struct page *lpage, unsigned loffs,
|
||||
int size, sector_t rblock)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = lo->transfer(lo, cmd, rpage, roffs, lpage, loffs, size, rblock);
|
||||
if (likely(!ret))
|
||||
return 0;
|
||||
|
||||
printk_ratelimited(KERN_ERR
|
||||
"loop: Transfer error at byte offset %llu, length %i.\n",
|
||||
(unsigned long long)rblock << 9, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lo_write_bvec(struct file *file, struct bio_vec *bvec, loff_t *ppos)
|
||||
{
|
||||
struct iov_iter i;
|
||||
@@ -343,41 +271,6 @@ static int lo_write_simple(struct loop_device *lo, struct request *rq,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the slow, transforming version that needs to double buffer the
|
||||
* data as it cannot do the transformations in place without having direct
|
||||
* access to the destination pages of the backing file.
|
||||
*/
|
||||
static int lo_write_transfer(struct loop_device *lo, struct request *rq,
|
||||
loff_t pos)
|
||||
{
|
||||
struct bio_vec bvec, b;
|
||||
struct req_iterator iter;
|
||||
struct page *page;
|
||||
int ret = 0;
|
||||
|
||||
page = alloc_page(GFP_NOIO);
|
||||
if (unlikely(!page))
|
||||
return -ENOMEM;
|
||||
|
||||
rq_for_each_segment(bvec, rq, iter) {
|
||||
ret = lo_do_transfer(lo, WRITE, page, 0, bvec.bv_page,
|
||||
bvec.bv_offset, bvec.bv_len, pos >> 9);
|
||||
if (unlikely(ret))
|
||||
break;
|
||||
|
||||
b.bv_page = page;
|
||||
b.bv_offset = 0;
|
||||
b.bv_len = bvec.bv_len;
|
||||
ret = lo_write_bvec(lo->lo_backing_file, &b, &pos);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
__free_page(page);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lo_read_simple(struct loop_device *lo, struct request *rq,
|
||||
loff_t pos)
|
||||
{
|
||||
@@ -407,64 +300,12 @@ static int lo_read_simple(struct loop_device *lo, struct request *rq,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lo_read_transfer(struct loop_device *lo, struct request *rq,
|
||||
loff_t pos)
|
||||
{
|
||||
struct bio_vec bvec, b;
|
||||
struct req_iterator iter;
|
||||
struct iov_iter i;
|
||||
struct page *page;
|
||||
ssize_t len;
|
||||
int ret = 0;
|
||||
|
||||
page = alloc_page(GFP_NOIO);
|
||||
if (unlikely(!page))
|
||||
return -ENOMEM;
|
||||
|
||||
rq_for_each_segment(bvec, rq, iter) {
|
||||
loff_t offset = pos;
|
||||
|
||||
b.bv_page = page;
|
||||
b.bv_offset = 0;
|
||||
b.bv_len = bvec.bv_len;
|
||||
|
||||
iov_iter_bvec(&i, READ, &b, 1, b.bv_len);
|
||||
len = vfs_iter_read(lo->lo_backing_file, &i, &pos, 0);
|
||||
if (len < 0) {
|
||||
ret = len;
|
||||
goto out_free_page;
|
||||
}
|
||||
|
||||
ret = lo_do_transfer(lo, READ, page, 0, bvec.bv_page,
|
||||
bvec.bv_offset, len, offset >> 9);
|
||||
if (ret)
|
||||
goto out_free_page;
|
||||
|
||||
flush_dcache_page(bvec.bv_page);
|
||||
|
||||
if (len != bvec.bv_len) {
|
||||
struct bio *bio;
|
||||
|
||||
__rq_for_each_bio(bio, rq)
|
||||
zero_fill_bio(bio);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out_free_page:
|
||||
__free_page(page);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lo_fallocate(struct loop_device *lo, struct request *rq, loff_t pos,
|
||||
int mode)
|
||||
{
|
||||
/*
|
||||
* We use fallocate to manipulate the space mappings used by the image
|
||||
* a.k.a. discard/zerorange. However we do not support this if
|
||||
* encryption is enabled, because it may give an attacker useful
|
||||
* information.
|
||||
* a.k.a. discard/zerorange.
|
||||
*/
|
||||
struct file *file = lo->lo_backing_file;
|
||||
struct request_queue *q = lo->lo_queue;
|
||||
@@ -647,16 +488,12 @@ static int do_req_filebacked(struct loop_device *lo, struct request *rq)
|
||||
case REQ_OP_DISCARD:
|
||||
return lo_fallocate(lo, rq, pos, FALLOC_FL_PUNCH_HOLE);
|
||||
case REQ_OP_WRITE:
|
||||
if (lo->transfer)
|
||||
return lo_write_transfer(lo, rq, pos);
|
||||
else if (cmd->use_aio)
|
||||
if (cmd->use_aio)
|
||||
return lo_rw_aio(lo, cmd, pos, WRITE);
|
||||
else
|
||||
return lo_write_simple(lo, rq, pos);
|
||||
case REQ_OP_READ:
|
||||
if (lo->transfer)
|
||||
return lo_read_transfer(lo, rq, pos);
|
||||
else if (cmd->use_aio)
|
||||
if (cmd->use_aio)
|
||||
return lo_rw_aio(lo, cmd, pos, READ);
|
||||
else
|
||||
return lo_read_simple(lo, rq, pos);
|
||||
@@ -921,7 +758,7 @@ static void loop_config_discard(struct loop_device *lo)
|
||||
* not blkdev_issue_discard(). This maintains consistent behavior with
|
||||
* file-backed loop devices: discarded regions read back as zero.
|
||||
*/
|
||||
if (S_ISBLK(inode->i_mode) && !lo->lo_encrypt_key_size) {
|
||||
if (S_ISBLK(inode->i_mode)) {
|
||||
struct request_queue *backingq = bdev_get_queue(I_BDEV(inode));
|
||||
|
||||
max_discard_sectors = backingq->limits.max_write_zeroes_sectors;
|
||||
@@ -930,11 +767,9 @@ static void loop_config_discard(struct loop_device *lo)
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* image a.k.a. discard.
|
||||
*/
|
||||
} else if (!file->f_op->fallocate || lo->lo_encrypt_key_size) {
|
||||
} else if (!file->f_op->fallocate) {
|
||||
max_discard_sectors = 0;
|
||||
granularity = 0;
|
||||
|
||||
@@ -1071,43 +906,6 @@ static void loop_update_rotational(struct loop_device *lo)
|
||||
blk_queue_flag_clear(QUEUE_FLAG_NONROT, q);
|
||||
}
|
||||
|
||||
static int
|
||||
loop_release_xfer(struct loop_device *lo)
|
||||
{
|
||||
int err = 0;
|
||||
struct loop_func_table *xfer = lo->lo_encryption;
|
||||
|
||||
if (xfer) {
|
||||
if (xfer->release)
|
||||
err = xfer->release(lo);
|
||||
lo->transfer = NULL;
|
||||
lo->lo_encryption = NULL;
|
||||
module_put(xfer->owner);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer,
|
||||
const struct loop_info64 *i)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (xfer) {
|
||||
struct module *owner = xfer->owner;
|
||||
|
||||
if (!try_module_get(owner))
|
||||
return -EINVAL;
|
||||
if (xfer->init)
|
||||
err = xfer->init(lo, i);
|
||||
if (err)
|
||||
module_put(owner);
|
||||
else
|
||||
lo->lo_encryption = xfer;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* loop_set_status_from_info - configure device from loop_info
|
||||
* @lo: struct loop_device to configure
|
||||
@@ -1120,55 +918,27 @@ static int
|
||||
loop_set_status_from_info(struct loop_device *lo,
|
||||
const struct loop_info64 *info)
|
||||
{
|
||||
int err;
|
||||
struct loop_func_table *xfer;
|
||||
kuid_t uid = current_uid();
|
||||
|
||||
if ((unsigned int) info->lo_encrypt_key_size > LO_KEY_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
err = loop_release_xfer(lo);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (info->lo_encrypt_type) {
|
||||
unsigned int type = info->lo_encrypt_type;
|
||||
|
||||
if (type >= MAX_LO_CRYPT)
|
||||
return -EINVAL;
|
||||
xfer = xfer_funcs[type];
|
||||
if (xfer == NULL)
|
||||
return -EINVAL;
|
||||
} else
|
||||
xfer = NULL;
|
||||
|
||||
err = loop_init_xfer(lo, xfer, info);
|
||||
if (err)
|
||||
return err;
|
||||
switch (info->lo_encrypt_type) {
|
||||
case LO_CRYPT_NONE:
|
||||
break;
|
||||
case LO_CRYPT_XOR:
|
||||
pr_warn("support for the xor transformation has been removed.\n");
|
||||
return -EINVAL;
|
||||
case LO_CRYPT_CRYPTOAPI:
|
||||
pr_warn("support for cryptoloop has been removed. Use dm-crypt instead.\n");
|
||||
return -EINVAL;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
lo->lo_offset = info->lo_offset;
|
||||
lo->lo_sizelimit = info->lo_sizelimit;
|
||||
memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE);
|
||||
memcpy(lo->lo_crypt_name, info->lo_crypt_name, LO_NAME_SIZE);
|
||||
lo->lo_file_name[LO_NAME_SIZE-1] = 0;
|
||||
lo->lo_crypt_name[LO_NAME_SIZE-1] = 0;
|
||||
|
||||
if (!xfer)
|
||||
xfer = &none_funcs;
|
||||
lo->transfer = xfer->transfer;
|
||||
lo->ioctl = xfer->ioctl;
|
||||
|
||||
lo->lo_flags = info->lo_flags;
|
||||
|
||||
lo->lo_encrypt_key_size = info->lo_encrypt_key_size;
|
||||
lo->lo_init[0] = info->lo_init[0];
|
||||
lo->lo_init[1] = info->lo_init[1];
|
||||
if (info->lo_encrypt_key_size) {
|
||||
memcpy(lo->lo_encrypt_key, info->lo_encrypt_key,
|
||||
info->lo_encrypt_key_size);
|
||||
lo->lo_key_owner = uid;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1367,16 +1137,9 @@ static int __loop_clr_fd(struct loop_device *lo, bool release)
|
||||
lo->lo_backing_file = NULL;
|
||||
spin_unlock_irq(&lo->lo_lock);
|
||||
|
||||
loop_release_xfer(lo);
|
||||
lo->transfer = NULL;
|
||||
lo->ioctl = NULL;
|
||||
lo->lo_device = NULL;
|
||||
lo->lo_encryption = NULL;
|
||||
lo->lo_offset = 0;
|
||||
lo->lo_sizelimit = 0;
|
||||
lo->lo_encrypt_key_size = 0;
|
||||
memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
|
||||
memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
|
||||
memset(lo->lo_file_name, 0, LO_NAME_SIZE);
|
||||
blk_queue_logical_block_size(lo->lo_queue, 512);
|
||||
blk_queue_physical_block_size(lo->lo_queue, 512);
|
||||
@@ -1478,7 +1241,6 @@ static int
|
||||
loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
|
||||
{
|
||||
int err;
|
||||
kuid_t uid = current_uid();
|
||||
int prev_lo_flags;
|
||||
bool partscan = false;
|
||||
bool size_changed = false;
|
||||
@@ -1486,12 +1248,6 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
|
||||
err = mutex_lock_killable(&lo->lo_mutex);
|
||||
if (err)
|
||||
return err;
|
||||
if (lo->lo_encrypt_key_size &&
|
||||
!uid_eq(lo->lo_key_owner, uid) &&
|
||||
!capable(CAP_SYS_ADMIN)) {
|
||||
err = -EPERM;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (lo->lo_state != Lo_bound) {
|
||||
err = -ENXIO;
|
||||
goto out_unlock;
|
||||
@@ -1577,14 +1333,6 @@ loop_get_status(struct loop_device *lo, struct loop_info64 *info)
|
||||
info->lo_sizelimit = lo->lo_sizelimit;
|
||||
info->lo_flags = lo->lo_flags;
|
||||
memcpy(info->lo_file_name, lo->lo_file_name, LO_NAME_SIZE);
|
||||
memcpy(info->lo_crypt_name, lo->lo_crypt_name, LO_NAME_SIZE);
|
||||
info->lo_encrypt_type =
|
||||
lo->lo_encryption ? lo->lo_encryption->number : 0;
|
||||
if (lo->lo_encrypt_key_size && capable(CAP_SYS_ADMIN)) {
|
||||
info->lo_encrypt_key_size = lo->lo_encrypt_key_size;
|
||||
memcpy(info->lo_encrypt_key, lo->lo_encrypt_key,
|
||||
lo->lo_encrypt_key_size);
|
||||
}
|
||||
|
||||
/* Drop lo_mutex while we call into the filesystem. */
|
||||
path = lo->lo_backing_file->f_path;
|
||||
@@ -1610,16 +1358,8 @@ loop_info64_from_old(const struct loop_info *info, struct loop_info64 *info64)
|
||||
info64->lo_rdevice = info->lo_rdevice;
|
||||
info64->lo_offset = info->lo_offset;
|
||||
info64->lo_sizelimit = 0;
|
||||
info64->lo_encrypt_type = info->lo_encrypt_type;
|
||||
info64->lo_encrypt_key_size = info->lo_encrypt_key_size;
|
||||
info64->lo_flags = info->lo_flags;
|
||||
info64->lo_init[0] = info->lo_init[0];
|
||||
info64->lo_init[1] = info->lo_init[1];
|
||||
if (info->lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
|
||||
memcpy(info64->lo_crypt_name, info->lo_name, LO_NAME_SIZE);
|
||||
else
|
||||
memcpy(info64->lo_file_name, info->lo_name, LO_NAME_SIZE);
|
||||
memcpy(info64->lo_encrypt_key, info->lo_encrypt_key, LO_KEY_SIZE);
|
||||
memcpy(info64->lo_file_name, info->lo_name, LO_NAME_SIZE);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1631,16 +1371,8 @@ loop_info64_to_old(const struct loop_info64 *info64, struct loop_info *info)
|
||||
info->lo_inode = info64->lo_inode;
|
||||
info->lo_rdevice = info64->lo_rdevice;
|
||||
info->lo_offset = info64->lo_offset;
|
||||
info->lo_encrypt_type = info64->lo_encrypt_type;
|
||||
info->lo_encrypt_key_size = info64->lo_encrypt_key_size;
|
||||
info->lo_flags = info64->lo_flags;
|
||||
info->lo_init[0] = info64->lo_init[0];
|
||||
info->lo_init[1] = info64->lo_init[1];
|
||||
if (info->lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
|
||||
memcpy(info->lo_name, info64->lo_crypt_name, LO_NAME_SIZE);
|
||||
else
|
||||
memcpy(info->lo_name, info64->lo_file_name, LO_NAME_SIZE);
|
||||
memcpy(info->lo_encrypt_key, info64->lo_encrypt_key, LO_KEY_SIZE);
|
||||
memcpy(info->lo_name, info64->lo_file_name, LO_NAME_SIZE);
|
||||
|
||||
/* error in case values were truncated */
|
||||
if (info->lo_device != info64->lo_device ||
|
||||
@@ -1789,7 +1521,7 @@ static int lo_simple_ioctl(struct loop_device *lo, unsigned int cmd,
|
||||
err = loop_set_block_size(lo, arg);
|
||||
break;
|
||||
default:
|
||||
err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL;
|
||||
err = -EINVAL;
|
||||
}
|
||||
mutex_unlock(&lo->lo_mutex);
|
||||
return err;
|
||||
@@ -1865,7 +1597,6 @@ struct compat_loop_info {
|
||||
compat_ulong_t lo_inode; /* ioctl r/o */
|
||||
compat_dev_t lo_rdevice; /* ioctl r/o */
|
||||
compat_int_t lo_offset;
|
||||
compat_int_t lo_encrypt_type;
|
||||
compat_int_t lo_encrypt_key_size; /* ioctl w/o */
|
||||
compat_int_t lo_flags; /* ioctl r/o */
|
||||
char lo_name[LO_NAME_SIZE];
|
||||
@@ -1894,16 +1625,8 @@ loop_info64_from_compat(const struct compat_loop_info __user *arg,
|
||||
info64->lo_rdevice = info.lo_rdevice;
|
||||
info64->lo_offset = info.lo_offset;
|
||||
info64->lo_sizelimit = 0;
|
||||
info64->lo_encrypt_type = info.lo_encrypt_type;
|
||||
info64->lo_encrypt_key_size = info.lo_encrypt_key_size;
|
||||
info64->lo_flags = info.lo_flags;
|
||||
info64->lo_init[0] = info.lo_init[0];
|
||||
info64->lo_init[1] = info.lo_init[1];
|
||||
if (info.lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
|
||||
memcpy(info64->lo_crypt_name, info.lo_name, LO_NAME_SIZE);
|
||||
else
|
||||
memcpy(info64->lo_file_name, info.lo_name, LO_NAME_SIZE);
|
||||
memcpy(info64->lo_encrypt_key, info.lo_encrypt_key, LO_KEY_SIZE);
|
||||
memcpy(info64->lo_file_name, info.lo_name, LO_NAME_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1923,24 +1646,14 @@ loop_info64_to_compat(const struct loop_info64 *info64,
|
||||
info.lo_inode = info64->lo_inode;
|
||||
info.lo_rdevice = info64->lo_rdevice;
|
||||
info.lo_offset = info64->lo_offset;
|
||||
info.lo_encrypt_type = info64->lo_encrypt_type;
|
||||
info.lo_encrypt_key_size = info64->lo_encrypt_key_size;
|
||||
info.lo_flags = info64->lo_flags;
|
||||
info.lo_init[0] = info64->lo_init[0];
|
||||
info.lo_init[1] = info64->lo_init[1];
|
||||
if (info.lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
|
||||
memcpy(info.lo_name, info64->lo_crypt_name, LO_NAME_SIZE);
|
||||
else
|
||||
memcpy(info.lo_name, info64->lo_file_name, LO_NAME_SIZE);
|
||||
memcpy(info.lo_encrypt_key, info64->lo_encrypt_key, LO_KEY_SIZE);
|
||||
memcpy(info.lo_name, info64->lo_file_name, LO_NAME_SIZE);
|
||||
|
||||
/* error in case values were truncated */
|
||||
if (info.lo_device != info64->lo_device ||
|
||||
info.lo_rdevice != info64->lo_rdevice ||
|
||||
info.lo_inode != info64->lo_inode ||
|
||||
info.lo_offset != info64->lo_offset ||
|
||||
info.lo_init[0] != info64->lo_init[0] ||
|
||||
info.lo_init[1] != info64->lo_init[1])
|
||||
info.lo_offset != info64->lo_offset)
|
||||
return -EOVERFLOW;
|
||||
|
||||
if (copy_to_user(arg, &info, sizeof(info)))
|
||||
@@ -2081,43 +1794,6 @@ MODULE_PARM_DESC(max_part, "Maximum number of partitions per loop device");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR);
|
||||
|
||||
int loop_register_transfer(struct loop_func_table *funcs)
|
||||
{
|
||||
unsigned int n = funcs->number;
|
||||
|
||||
if (n >= MAX_LO_CRYPT || xfer_funcs[n])
|
||||
return -EINVAL;
|
||||
xfer_funcs[n] = funcs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int loop_unregister_transfer(int number)
|
||||
{
|
||||
unsigned int n = number;
|
||||
struct loop_func_table *xfer;
|
||||
|
||||
if (n == 0 || n >= MAX_LO_CRYPT || (xfer = xfer_funcs[n]) == NULL)
|
||||
return -EINVAL;
|
||||
/*
|
||||
* This function is called from only cleanup_cryptoloop().
|
||||
* Given that each loop device that has a transfer enabled holds a
|
||||
* reference to the module implementing it we should never get here
|
||||
* with a transfer that is set (unless forced module unloading is
|
||||
* requested). Thus, check module's refcount and warn if this is
|
||||
* not a clean unloading.
|
||||
*/
|
||||
#ifdef CONFIG_MODULE_UNLOAD
|
||||
if (xfer->owner && module_refcount(xfer->owner) != -1)
|
||||
pr_err("Danger! Unregistering an in use transfer function.\n");
|
||||
#endif
|
||||
|
||||
xfer_funcs[n] = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(loop_register_transfer);
|
||||
EXPORT_SYMBOL(loop_unregister_transfer);
|
||||
|
||||
static blk_status_t loop_queue_rq(struct blk_mq_hw_ctx *hctx,
|
||||
const struct blk_mq_queue_data *bd)
|
||||
{
|
||||
@@ -2374,13 +2050,19 @@ static int loop_add(int i)
|
||||
disk->event_flags = DISK_EVENT_FLAG_UEVENT;
|
||||
sprintf(disk->disk_name, "loop%d", i);
|
||||
/* Make this loop device reachable from pathname. */
|
||||
add_disk(disk);
|
||||
err = add_disk(disk);
|
||||
if (err)
|
||||
goto out_cleanup_disk;
|
||||
|
||||
/* Show this loop device. */
|
||||
mutex_lock(&loop_ctl_mutex);
|
||||
lo->idr_visible = true;
|
||||
mutex_unlock(&loop_ctl_mutex);
|
||||
|
||||
return i;
|
||||
|
||||
out_cleanup_disk:
|
||||
blk_cleanup_disk(disk);
|
||||
out_cleanup_tags:
|
||||
blk_mq_free_tag_set(&lo->tag_set);
|
||||
out_free_idr:
|
||||
|
||||
Reference in New Issue
Block a user