summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Bauer2020-05-29 14:37:49 +0200
committerJonathan Bauer2020-05-29 14:37:49 +0200
commit1bdbdfdf12ae35f08f5dcbec06a35c8d0f11ef55 (patch)
tree2e64659e53742b64f598b2e36a1d3cb32d1371b9
parentInitial code from Manuel Bentele (diff)
downloadxloop-1bdbdfdf12ae35f08f5dcbec06a35c8d0f11ef55.tar.gz
xloop-1bdbdfdf12ae35f08f5dcbec06a35c8d0f11ef55.tar.xz
xloop-1bdbdfdf12ae35f08f5dcbec06a35c8d0f11ef55.zip
Initial working state
* Moved old Makefile to Kbuild.in * New Makefile to compile against running kernel (or KDIR) * Moved file format defines from loop/include/uapi/linux/loop.h to loop_file_fmt.h * Moved definitions of loop_info{,64} to loop_file_fmt.h * Renamed loop_info{,64} to xloop_info{,64} * Removed checks for file format support which was now unneeded
-rw-r--r--Kbuild.in11
-rw-r--r--Makefile15
-rw-r--r--README.md15
-rw-r--r--loop_file_fmt.h6
-rw-r--r--loop_main.c120
-rw-r--r--loop_main.h35
6 files changed, 106 insertions, 96 deletions
diff --git a/Kbuild.in b/Kbuild.in
new file mode 100644
index 0000000..c50333a
--- /dev/null
+++ b/Kbuild.in
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0
+
+loop-y += loop_main.o loop_file_fmt.o
+obj-$(CONFIG_BLK_DEV_LOOP) += loop.o
+
+obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryptoloop.o
+
+obj-$(CONFIG_BLK_DEV_LOOP_FILE_FMT_RAW) += loop_file_fmt_raw.o
+
+loop_file_fmt_qcow-y += loop_file_fmt_qcow_main.o loop_file_fmt_qcow_cluster.o loop_file_fmt_qcow_cache.o
+obj-$(CONFIG_BLK_DEV_LOOP_FILE_FMT_QCOW) += loop_file_fmt_qcow.o
diff --git a/Makefile b/Makefile
index a82cd7a..b7f2191 100644
--- a/Makefile
+++ b/Makefile
@@ -1,11 +1,12 @@
# SPDX-License-Identifier: GPL-2.0
+include $(PWD)/Kbuild.in
-loop-y += loop_main.o loop_file_fmt.o
-obj-$(CONFIG_BLK_DEV_LOOP) += loop.o
+ifndef KDIR
+ KDIR = /lib/modules/$(shell uname -r)/build
+endif
-obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryptoloop.o
+all:
+ make -C "$(KDIR)" "M=$(PWD)" modules
-obj-$(CONFIG_BLK_DEV_LOOP_FILE_FMT_RAW) += loop_file_fmt_raw.o
-
-loop_file_fmt_qcow-y += loop_file_fmt_qcow_main.o loop_file_fmt_qcow_cluster.o loop_file_fmt_qcow_cache.o
-obj-$(CONFIG_BLK_DEV_LOOP_FILE_FMT_QCOW) += loop_file_fmt_qcow.o
+clean:
+ make -C "$(KDIR)" "M=$(PWD)" clean
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e32b858
--- /dev/null
+++ b/README.md
@@ -0,0 +1,15 @@
+Building the modules:
+
+```shell
+$ make CONFIG_BLK_DEV_LOOP_FILE_FMT_QCOW=m CONFIG_BLK_DEV_LOOP_FILE_FMT_RAW=m
+```
+
+Results in:
+* xloop.ko
+* loop_file_fmt_raw.ko
+* loop_file_fmt_qcow.ko
+
+Clean:
+```shell
+$ make clean
+```
diff --git a/loop_file_fmt.h b/loop_file_fmt.h
index 5c0e493..8a16c86 100644
--- a/loop_file_fmt.h
+++ b/loop_file_fmt.h
@@ -14,6 +14,12 @@
struct loop_file_fmt;
+#define LO_FILE_FMT_RAW 0
+#define LO_FILE_FMT_QCOW 1
+#define LO_FILE_FMT_VDI 2
+#define LO_FILE_FMT_VMDK 3
+#define MAX_LO_FILE_FMT (LO_FILE_FMT_VMDK + 1)
+
/**
* struct loop_file_fmt_ops - File format subsystem operations
*
diff --git a/loop_main.c b/loop_main.c
index 7c1bb19..3bf4f1f 100644
--- a/loop_main.c
+++ b/loop_main.c
@@ -121,7 +121,7 @@ static int transfer_xor(struct loop_device *lo, int cmd,
return 0;
}
-static int xor_init(struct loop_device *lo, const struct loop_info64 *info)
+static int xor_init(struct loop_device *lo, const struct xloop_info64 *info)
{
if (unlikely(info->lo_encrypt_key_size <= 0))
return -EINVAL;
@@ -741,7 +741,7 @@ loop_release_xfer(struct loop_device *lo)
static int
loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer,
- const struct loop_info64 *i)
+ const struct xloop_info64 *i)
{
int err = 0;
@@ -906,7 +906,7 @@ static int loop_clr_fd(struct loop_device *lo)
}
static int
-loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
+loop_set_status(struct loop_device *lo, const struct xloop_info64 *info)
{
int err;
struct loop_func_table *xfer;
@@ -1043,7 +1043,7 @@ out_unlock:
}
static int
-loop_get_status(struct loop_device *lo, struct loop_info64 *info)
+loop_get_status(struct loop_device *lo, struct xloop_info64 *info)
{
struct path path;
struct kstat stat;
@@ -1088,7 +1088,7 @@ loop_get_status(struct loop_device *lo, struct loop_info64 *info)
}
static void
-loop_info64_from_old(const struct loop_info *info, struct loop_info64 *info64)
+loop_info64_from_old(const struct xloop_info *info, struct xloop_info64 *info64)
{
memset(info64, 0, sizeof(*info64));
info64->lo_number = info->lo_number;
@@ -1111,7 +1111,7 @@ loop_info64_from_old(const struct loop_info *info, struct loop_info64 *info64)
}
static int
-loop_info64_to_old(const struct loop_info64 *info64, struct loop_info *info)
+loop_info64_to_old(const struct xloop_info64 *info64, struct xloop_info *info)
{
memset(info, 0, sizeof(*info));
info->lo_number = info64->lo_number;
@@ -1142,61 +1142,39 @@ loop_info64_to_old(const struct loop_info64 *info64, struct loop_info *info)
}
static int
-loop_set_status_old(struct loop_device *lo, const struct loop_info __user *arg)
+loop_set_status_old(struct loop_device *lo, const struct xloop_info __user *arg)
{
- struct loop_info info;
- struct loop_info64 info64;
+ struct xloop_info info;
+ struct xloop_info64 info64;
int err;
- /* backward compatibility: copy everything except the file format type
- * field */
- err = copy_from_user(&info, arg,
- sizeof(info) - sizeof(info.lo_file_fmt_type));
+ /* copy everything from the user space */
+ err = copy_from_user(&info, arg, sizeof(info));
if (err)
return -EFAULT;
- if (info.lo_flags & LO_FLAGS_FILE_FMT) {
- /* copy everything from the user space */
- err = copy_from_user(&info, arg, sizeof(info));
- if (err)
- return -EFAULT;
- } else {
- info64.lo_file_fmt_type = LO_FILE_FMT_RAW;
- }
-
loop_info64_from_old(&info, &info64);
return loop_set_status(lo, &info64);
}
static int
-loop_set_status64(struct loop_device *lo, const struct loop_info64 __user *arg)
+loop_set_status64(struct loop_device *lo, const struct xloop_info64 __user *arg)
{
- struct loop_info64 info64;
+ struct xloop_info64 info64;
int err;
- /* backward compatibility: copy everything except the file format type
- * field */
- err = copy_from_user(&info64, arg,
- sizeof(info64) - sizeof(info64.lo_file_fmt_type));
+ /* copy everything from the user space */
+ err = copy_from_user(&info64, arg, sizeof(info64));
if (err)
return -EFAULT;
- if (info64.lo_flags & LO_FLAGS_FILE_FMT) {
- /* copy everything from the user space */
- err = copy_from_user(&info64, arg, sizeof(info64));
- if (err)
- return -EFAULT;
- } else {
- info64.lo_file_fmt_type = LO_FILE_FMT_RAW;
- }
-
return loop_set_status(lo, &info64);
}
static int
-loop_get_status_old(struct loop_device *lo, struct loop_info __user *arg) {
- struct loop_info info;
- struct loop_info64 info64;
+loop_get_status_old(struct loop_device *lo, struct xloop_info __user *arg) {
+ struct xloop_info info;
+ struct xloop_info64 info64;
int lo_flags;
int err;
@@ -1216,15 +1194,7 @@ loop_get_status_old(struct loop_device *lo, struct loop_info __user *arg) {
if (!err)
err = loop_info64_to_old(&info64, &info);
- if (lo_flags & LO_FLAGS_FILE_FMT) {
- /* copy entire structure to user space because file format
- * support is available */
- err = copy_to_user(arg, &info, sizeof(info));
- } else {
- /* copy normal structure to user space */
- err = copy_to_user(arg, &info,
- sizeof(info) - sizeof(info.lo_file_fmt_type));
- }
+ err = copy_to_user(arg, &info, sizeof(info));
if (err)
return -EFAULT;
@@ -1233,8 +1203,8 @@ loop_get_status_old(struct loop_device *lo, struct loop_info __user *arg) {
}
static int
-loop_get_status64(struct loop_device *lo, struct loop_info64 __user *arg) {
- struct loop_info64 info64;
+loop_get_status64(struct loop_device *lo, struct xloop_info64 __user *arg) {
+ struct xloop_info64 info64;
u32 lo_flags;
int err;
@@ -1254,15 +1224,7 @@ loop_get_status64(struct loop_device *lo, struct loop_info64 __user *arg) {
if (err)
return -EFAULT;
- if (lo_flags & LO_FLAGS_FILE_FMT) {
- /* copy entire structure to user space because file format
- * support is available */
- err = copy_to_user(arg, &info64, sizeof(info64));
- } else {
- /* copy normal structure to user space */
- err = copy_to_user(arg, &info64,
- sizeof(info64) - sizeof(info64.lo_file_fmt_type));
- }
+ err = copy_to_user(arg, &info64, sizeof(info64));
if (err)
return -EFAULT;
@@ -1371,20 +1333,20 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode,
err = -EPERM;
if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) {
err = loop_set_status_old(lo,
- (struct loop_info __user *)arg);
+ (struct xloop_info __user *)arg);
}
break;
case LOOP_GET_STATUS:
- return loop_get_status_old(lo, (struct loop_info __user *) arg);
+ return loop_get_status_old(lo, (struct xloop_info __user *) arg);
case LOOP_SET_STATUS64:
err = -EPERM;
if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) {
err = loop_set_status64(lo,
- (struct loop_info64 __user *) arg);
+ (struct xloop_info64 __user *) arg);
}
break;
case LOOP_GET_STATUS64:
- return loop_get_status64(lo, (struct loop_info64 __user *) arg);
+ return loop_get_status64(lo, (struct xloop_info64 __user *) arg);
case LOOP_SET_CAPACITY:
case LOOP_SET_DIRECT_IO:
case LOOP_SET_BLOCK_SIZE:
@@ -1422,27 +1384,17 @@ struct compat_loop_info {
*/
static noinline int
loop_info64_from_compat(const struct compat_loop_info __user *arg,
- struct loop_info64 *info64)
+ struct xloop_info64 *info64)
{
struct compat_loop_info info;
int err;
/* backward compatibility: copy everything except the file format type
* field */
- err = copy_from_user(&info, arg,
- sizeof(info) - sizeof(info.lo_file_fmt_type));
+ err = copy_from_user(&info, arg, sizeof(info));
if (err)
return -EFAULT;
- if (info.lo_flags & LO_FLAGS_FILE_FMT) {
- /* copy everything from the user space */
- err = copy_from_user(&info, arg, sizeof(info));
- if (err)
- return -EFAULT;
- } else {
- info.lo_file_fmt_type = LO_FILE_FMT_RAW;
- }
-
memset(info64, 0, sizeof(*info64));
info64->lo_number = info.lo_number;
info64->lo_device = info.lo_device;
@@ -1469,7 +1421,7 @@ loop_info64_from_compat(const struct compat_loop_info __user *arg,
* - noinlined to reduce stack space usage in main part of driver
*/
static noinline int
-loop_info64_to_compat(const struct loop_info64 *info64,
+loop_info64_to_compat(const struct xloop_info64 *info64,
struct compat_loop_info __user *arg)
{
struct compat_loop_info info;
@@ -1513,15 +1465,7 @@ loop_info64_to_compat(const struct loop_info64 *info64,
info.lo_file_fmt_type != info64->lo_file_fmt_type)
return -EOVERFLOW;
- if (lo_flags & LO_FLAGS_FILE_FMT) {
- /* copy entire structure to user space because file format
- * support is available */
- err = copy_to_user(arg, &info, sizeof(info));
- } else {
- /* copy normal structure to user space */
- err = copy_to_user(arg, &info,
- sizeof(info) - sizeof(info.lo_file_fmt_type));
- }
+ err = copy_to_user(arg, &info, sizeof(info));
if (err)
return -EFAULT;
@@ -1533,7 +1477,7 @@ static int
loop_set_status_compat(struct loop_device *lo,
const struct compat_loop_info __user *arg)
{
- struct loop_info64 info64;
+ struct xloop_info64 info64;
int ret;
ret = loop_info64_from_compat(arg, &info64);
@@ -1546,7 +1490,7 @@ static int
loop_get_status_compat(struct loop_device *lo,
struct compat_loop_info __user *arg)
{
- struct loop_info64 info64;
+ struct xloop_info64 info64;
int err;
if (!arg)
diff --git a/loop_main.h b/loop_main.h
index 33f6578..324ec2e 100644
--- a/loop_main.h
+++ b/loop_main.h
@@ -32,6 +32,39 @@ enum {
struct loop_func_table;
+struct xloop_info {
+ int lo_number; /* ioctl r/o */
+ __kernel_old_dev_t lo_device; /* ioctl r/o */
+ unsigned long lo_inode; /* ioctl r/o */
+ __kernel_old_dev_t lo_rdevice; /* ioctl r/o */
+ int lo_offset;
+ int lo_encrypt_type;
+ int lo_encrypt_key_size; /* ioctl w/o */
+ int lo_flags; /* ioctl r/o */
+ char lo_name[LO_NAME_SIZE];
+ unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
+ unsigned long lo_init[2];
+ char reserved[4];
+ int lo_file_fmt_type;
+};
+
+struct xloop_info64 {
+ __u64 lo_device; /* ioctl r/o */
+ __u64 lo_inode; /* ioctl r/o */
+ __u64 lo_rdevice; /* ioctl r/o */
+ __u64 lo_offset;
+ __u64 lo_sizelimit;/* bytes, 0 == max available */
+ __u32 lo_number; /* ioctl r/o */
+ __u32 lo_encrypt_type;
+ __u32 lo_encrypt_key_size; /* ioctl w/o */
+ __u32 lo_flags; /* ioctl r/o */
+ __u8 lo_file_name[LO_NAME_SIZE];
+ __u8 lo_crypt_name[LO_NAME_SIZE];
+ __u8 lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
+ __u64 lo_init[2];
+ __u32 lo_file_fmt_type;
+} __attribute__((packed));
+
struct loop_device {
int lo_number;
atomic_t lo_refcnt;
@@ -93,7 +126,7 @@ struct loop_func_table {
struct page *raw_page, unsigned raw_off,
struct page *loop_page, unsigned loop_off,
int size, sector_t real_block);
- int (*init)(struct loop_device *, const struct loop_info64 *);
+ int (*init)(struct loop_device *, const struct xloop_info64 *);
/* release is called from loop_unregister_transfer or clr_fd */
int (*release)(struct loop_device *);
int (*ioctl)(struct loop_device *, int cmd, unsigned long arg);