Commit eb63bae1 authored by Andries E. Brouwer's avatar Andries E. Brouwer Committed by Arnaldo Carvalho de Melo

[PATCH] loop.c cleanups

This does the following:
 - remove trailing spaces
 - make loop.h independent by including bio.h, blk.h, spinlock.h
 - replace the lock/unlock functions by module_get/module_put;
   in struct loop this is the change
	-       void (*lock)(struct loop_device *);
	-       void (*unlock)(struct loop_device *);
	+       struct module *owner;
 - replace the integer lo_encrypt_type by the pointer lo_encryption;
   there was a race with loop_unregister_transfer
 - fixed an off-by-one in loop_register_transfer

This is Step 1 of a series of half a dozen or so.

Half of the above is from Jari. Anything that is wrong is mine.
parent b42db0f5
...@@ -60,12 +60,10 @@ ...@@ -60,12 +60,10 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/bio.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/major.h> #include <linux/major.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/blk.h>
#include <linux/blkpg.h> #include <linux/blkpg.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/devfs_fs_kernel.h> #include <linux/devfs_fs_kernel.h>
...@@ -144,7 +142,8 @@ struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = { ...@@ -144,7 +142,8 @@ struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = {
&xor_funcs &xor_funcs
}; };
static int figure_loop_size(struct loop_device *lo) static int
figure_loop_size(struct loop_device *lo)
{ {
loff_t size = lo->lo_backing_file->f_dentry->d_inode->i_mapping->host->i_size; loff_t size = lo->lo_backing_file->f_dentry->d_inode->i_mapping->host->i_size;
sector_t x; sector_t x;
...@@ -154,14 +153,16 @@ static int figure_loop_size(struct loop_device *lo) ...@@ -154,14 +153,16 @@ static int figure_loop_size(struct loop_device *lo)
*/ */
size = (size - lo->lo_offset) >> 9; size = (size - lo->lo_offset) >> 9;
x = (sector_t)size; x = (sector_t)size;
if ((loff_t)x != size) if ((loff_t)x != size)
return -EFBIG; return -EFBIG;
set_capacity(disks[lo->lo_number], size); set_capacity(disks[lo->lo_number], x);
return 0; return 0;
} }
static inline int lo_do_transfer(struct loop_device *lo, int cmd, char *rbuf, static inline int
lo_do_transfer(struct loop_device *lo, int cmd, char *rbuf,
char *lbuf, int size, sector_t rblock) char *lbuf, int size, sector_t rblock)
{ {
if (!lo->transfer) if (!lo->transfer)
...@@ -614,9 +615,12 @@ static int loop_thread(void *data) ...@@ -614,9 +615,12 @@ static int loop_thread(void *data)
daemonize("loop%d", lo->lo_number); daemonize("loop%d", lo->lo_number);
current->flags |= PF_IOTHREAD; /* loop can be used in an encrypted device /*
hence, it mustn't be stopped at all because it could * loop can be used in an encrypted device,
be indirectly used during suspension */ * hence, it mustn't be stopped at all
* because it could be indirectly used during suspension
*/
current->flags |= PF_IOTHREAD;
set_user_nice(current, -20); set_user_nice(current, -20);
...@@ -771,33 +775,39 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file, ...@@ -771,33 +775,39 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
return error; return error;
} }
static int loop_release_xfer(struct loop_device *lo) static int
loop_release_xfer(struct loop_device *lo)
{ {
int err = 0; int err = 0;
if (lo->lo_encrypt_type) { struct loop_func_table *xfer = lo->lo_encryption;
struct loop_func_table *xfer= xfer_funcs[lo->lo_encrypt_type];
if (xfer && xfer->release) if (xfer) {
if (xfer->release)
err = xfer->release(lo); err = xfer->release(lo);
if (xfer && xfer->unlock) lo->transfer = NULL;
xfer->unlock(lo); lo->lo_encryption = NULL;
lo->lo_encrypt_type = 0; module_put(xfer->owner);
} }
return err; return err;
} }
static int static int
loop_init_xfer(struct loop_device *lo, int type, const struct loop_info64 *i) loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer,
const struct loop_info64 *i)
{ {
int err = 0; int err = 0;
if (type) {
struct loop_func_table *xfer = xfer_funcs[type]; if (xfer) {
struct module *owner = xfer->owner;
if (!try_module_get(owner))
return -EINVAL;
if (xfer->init) if (xfer->init)
err = xfer->init(lo, i); err = xfer->init(lo, i);
if (!err) { if (err)
lo->lo_encrypt_type = type; module_put(owner);
if (xfer->lock) else
xfer->lock(lo); lo->lo_encryption = xfer;
}
} }
return err; return err;
} }
...@@ -809,9 +819,11 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) ...@@ -809,9 +819,11 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
if (lo->lo_state != Lo_bound) if (lo->lo_state != Lo_bound)
return -ENXIO; return -ENXIO;
if (lo->lo_refcnt > 1) /* we needed one fd for the ioctl */ if (lo->lo_refcnt > 1) /* we needed one fd for the ioctl */
return -EBUSY; return -EBUSY;
if (filp==NULL)
if (filp == NULL)
return -EINVAL; return -EINVAL;
spin_lock_irq(&lo->lo_lock); spin_lock_irq(&lo->lo_lock);
...@@ -828,7 +840,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) ...@@ -828,7 +840,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
lo->transfer = NULL; lo->transfer = NULL;
lo->ioctl = NULL; lo->ioctl = NULL;
lo->lo_device = NULL; lo->lo_device = NULL;
lo->lo_encrypt_type = 0; lo->lo_encryption = NULL;
lo->lo_offset = 0; lo->lo_offset = 0;
lo->lo_encrypt_key_size = 0; lo->lo_encrypt_key_size = 0;
lo->lo_flags = 0; lo->lo_flags = 0;
...@@ -849,8 +861,7 @@ static int ...@@ -849,8 +861,7 @@ static int
loop_set_status(struct loop_device *lo, const struct loop_info64 *info) loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
{ {
int err; int err;
unsigned int type; struct loop_func_table *xfer;
loff_t offset;
if (lo->lo_encrypt_key_size && lo->lo_key_owner != current->uid && if (lo->lo_encrypt_key_size && lo->lo_key_owner != current->uid &&
!capable(CAP_SYS_ADMIN)) !capable(CAP_SYS_ADMIN))
...@@ -859,32 +870,39 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) ...@@ -859,32 +870,39 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
return -ENXIO; return -ENXIO;
if ((unsigned int) info->lo_encrypt_key_size > LO_KEY_SIZE) if ((unsigned int) info->lo_encrypt_key_size > LO_KEY_SIZE)
return -EINVAL; return -EINVAL;
type = info->lo_encrypt_type;
if (type >= MAX_LO_CRYPT || xfer_funcs[type] == NULL)
return -EINVAL;
if (type == LO_CRYPT_XOR && info->lo_encrypt_key_size == 0)
return -EINVAL;
err = loop_release_xfer(lo); err = loop_release_xfer(lo);
if (!err) if (err)
err = loop_init_xfer(lo, type, info); return err;
offset = lo->lo_offset; if (info->lo_encrypt_type) {
if (offset != info->lo_offset) { unsigned int type = info->lo_encrypt_type;
lo->lo_offset = info->lo_offset;
if (figure_loop_size(lo)){ if (type >= MAX_LO_CRYPT)
err = -EFBIG; return -EINVAL;
lo->lo_offset = offset; xfer = xfer_funcs[type];
} if (xfer == NULL)
} return -EINVAL;
} else
xfer = NULL;
err = loop_init_xfer(lo, xfer, info);
if (err) if (err)
return err; return err;
if (lo->lo_offset != info->lo_offset) {
lo->lo_offset = info->lo_offset;
if (figure_loop_size(lo))
return -EFBIG;
}
strlcpy(lo->lo_name, info->lo_name, LO_NAME_SIZE); strlcpy(lo->lo_name, info->lo_name, LO_NAME_SIZE);
lo->transfer = xfer_funcs[type]->transfer; if (!xfer)
lo->ioctl = xfer_funcs[type]->ioctl; xfer = &none_funcs;
lo->transfer = xfer->transfer;
lo->ioctl = xfer->ioctl;
lo->lo_encrypt_key_size = info->lo_encrypt_key_size; lo->lo_encrypt_key_size = info->lo_encrypt_key_size;
lo->lo_init[0] = info->lo_init[0]; lo->lo_init[0] = info->lo_init[0];
lo->lo_init[1] = info->lo_init[1]; lo->lo_init[1] = info->lo_init[1];
...@@ -917,7 +935,8 @@ loop_get_status(struct loop_device *lo, struct loop_info64 *info) ...@@ -917,7 +935,8 @@ loop_get_status(struct loop_device *lo, struct loop_info64 *info)
info->lo_offset = lo->lo_offset; info->lo_offset = lo->lo_offset;
info->lo_flags = lo->lo_flags; info->lo_flags = lo->lo_flags;
strlcpy(info->lo_name, lo->lo_name, LO_NAME_SIZE); strlcpy(info->lo_name, lo->lo_name, LO_NAME_SIZE);
info->lo_encrypt_type = lo->lo_encrypt_type; info->lo_encrypt_type =
lo->lo_encryption ? lo->lo_encryption->number : 0;
if (lo->lo_encrypt_key_size && capable(CAP_SYS_ADMIN)) { if (lo->lo_encrypt_key_size && capable(CAP_SYS_ADMIN)) {
info->lo_encrypt_key_size = lo->lo_encrypt_key_size; info->lo_encrypt_key_size = lo->lo_encrypt_key_size;
memcpy(info->lo_encrypt_key, lo->lo_encrypt_key, memcpy(info->lo_encrypt_key, lo->lo_encrypt_key,
...@@ -1060,30 +1079,22 @@ static int lo_ioctl(struct inode * inode, struct file * file, ...@@ -1060,30 +1079,22 @@ static int lo_ioctl(struct inode * inode, struct file * file,
static int lo_open(struct inode *inode, struct file *file) static int lo_open(struct inode *inode, struct file *file)
{ {
struct loop_device *lo = inode->i_bdev->bd_disk->private_data; struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
int type;
down(&lo->lo_ctl_mutex); down(&lo->lo_ctl_mutex);
type = lo->lo_encrypt_type;
if (type && xfer_funcs[type] && xfer_funcs[type]->lock)
xfer_funcs[type]->lock(lo);
lo->lo_refcnt++; lo->lo_refcnt++;
up(&lo->lo_ctl_mutex); up(&lo->lo_ctl_mutex);
return 0; return 0;
} }
static int lo_release(struct inode *inode, struct file *file) static int lo_release(struct inode *inode, struct file *file)
{ {
struct loop_device *lo = inode->i_bdev->bd_disk->private_data; struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
int type;
down(&lo->lo_ctl_mutex); down(&lo->lo_ctl_mutex);
type = lo->lo_encrypt_type;
--lo->lo_refcnt; --lo->lo_refcnt;
if (xfer_funcs[type] && xfer_funcs[type]->unlock)
xfer_funcs[type]->unlock(lo);
up(&lo->lo_ctl_mutex); up(&lo->lo_ctl_mutex);
return 0; return 0;
} }
...@@ -1103,27 +1114,34 @@ MODULE_LICENSE("GPL"); ...@@ -1103,27 +1114,34 @@ MODULE_LICENSE("GPL");
int loop_register_transfer(struct loop_func_table *funcs) int loop_register_transfer(struct loop_func_table *funcs)
{ {
if ((unsigned)funcs->number > MAX_LO_CRYPT || xfer_funcs[funcs->number]) unsigned int n = funcs->number;
if (n >= MAX_LO_CRYPT || xfer_funcs[n])
return -EINVAL; return -EINVAL;
xfer_funcs[funcs->number] = funcs; xfer_funcs[n] = funcs;
return 0; return 0;
} }
int loop_unregister_transfer(int number) int loop_unregister_transfer(int number)
{ {
unsigned int n = number;
struct loop_device *lo; struct loop_device *lo;
struct loop_func_table *xfer;
if ((unsigned)number >= MAX_LO_CRYPT) if (n == 0 || n >= MAX_LO_CRYPT || (xfer = xfer_funcs[n]) == NULL)
return -EINVAL; return -EINVAL;
xfer_funcs[n] = NULL;
for (lo = &loop_dev[0]; lo < &loop_dev[max_loop]; lo++) { for (lo = &loop_dev[0]; lo < &loop_dev[max_loop]; lo++) {
int type = lo->lo_encrypt_type; down(&lo->lo_ctl_mutex);
if (type == number) {
xfer_funcs[type]->release(lo); if (lo->lo_encryption == xfer)
lo->transfer = NULL; loop_release_xfer(lo);
lo->lo_encrypt_type = 0;
} up(&lo->lo_ctl_mutex);
} }
xfer_funcs[number] = NULL;
return 0; return 0;
} }
...@@ -1193,6 +1211,7 @@ int __init loop_init(void) ...@@ -1193,6 +1211,7 @@ int __init loop_init(void)
void loop_exit(void) void loop_exit(void)
{ {
int i; int i;
for (i = 0; i < max_loop; i++) { for (i = 0; i < max_loop; i++) {
del_gendisk(disks[i]); del_gendisk(disks[i]);
put_disk(disks[i]); put_disk(disks[i]);
......
...@@ -14,6 +14,9 @@ ...@@ -14,6 +14,9 @@
#define LO_KEY_SIZE 32 #define LO_KEY_SIZE 32
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/bio.h>
#include <linux/blk.h>
#include <linux/spinlock.h>
/* Possible states of device */ /* Possible states of device */
enum { enum {
...@@ -22,18 +25,20 @@ enum { ...@@ -22,18 +25,20 @@ enum {
Lo_rundown, Lo_rundown,
}; };
struct loop_func_table;
struct loop_device { struct loop_device {
int lo_number; int lo_number;
int lo_refcnt; int lo_refcnt;
int lo_offset; int lo_offset;
int lo_encrypt_type;
int lo_encrypt_key_size;
int lo_flags; int lo_flags;
int (*transfer)(struct loop_device *, int cmd, int (*transfer)(struct loop_device *, int cmd,
char *raw_buf, char *loop_buf, int size, char *raw_buf, char *loop_buf, int size,
sector_t real_block); sector_t real_block);
char lo_name[LO_NAME_SIZE]; char lo_name[LO_NAME_SIZE];
char lo_encrypt_key[LO_KEY_SIZE]; char lo_encrypt_key[LO_KEY_SIZE];
int lo_encrypt_key_size;
struct loop_func_table *lo_encryption;
__u32 lo_init[2]; __u32 lo_init[2];
uid_t lo_key_owner; /* Who set the key */ uid_t lo_key_owner; /* Who set the key */
int (*ioctl)(struct loop_device *, int cmd, int (*ioctl)(struct loop_device *, int cmd,
...@@ -129,9 +134,7 @@ struct loop_func_table { ...@@ -129,9 +134,7 @@ struct loop_func_table {
/* release is called from loop_unregister_transfer or clr_fd */ /* release is called from loop_unregister_transfer or clr_fd */
int (*release)(struct loop_device *); int (*release)(struct loop_device *);
int (*ioctl)(struct loop_device *, int cmd, unsigned long arg); int (*ioctl)(struct loop_device *, int cmd, unsigned long arg);
/* lock and unlock manage the module use counts */ struct module *owner;
void (*lock)(struct loop_device *);
void (*unlock)(struct loop_device *);
}; };
int loop_register_transfer(struct loop_func_table *funcs); int loop_register_transfer(struct loop_func_table *funcs);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment