diff options
Diffstat (limited to 'loop_file_fmt.c')
-rw-r--r-- | loop_file_fmt.c | 227 |
1 files changed, 123 insertions, 104 deletions
diff --git a/loop_file_fmt.c b/loop_file_fmt.c index ff356f1..062ea0d 100644 --- a/loop_file_fmt.c +++ b/loop_file_fmt.c @@ -2,7 +2,7 @@ /* * loop_file_fmt.c * - * File format subsystem for the loop device module. + * File format subsystem for the xloop device module. * * Copyright (C) 2019 Manuel Bentele <development@manuel-bentele.de> */ @@ -13,316 +13,335 @@ #include "loop_file_fmt.h" /* storage for all registered file format drivers */ -static struct loop_file_fmt_driver *loop_file_fmt_drivers[MAX_LO_FILE_FMT] = { +static struct xloop_file_fmt_driver *xloop_file_fmt_drivers[MAX_XLO_FILE_FMT] = { NULL }; -int loop_file_fmt_register_driver(struct loop_file_fmt_driver *drv) +int xloop_file_fmt_register_driver(struct xloop_file_fmt_driver *drv) { int ret = 0; if (drv == NULL) return -EFAULT; - if (drv->file_fmt_type > MAX_LO_FILE_FMT) + if (drv->file_fmt_type > MAX_XLO_FILE_FMT) return -EINVAL; - if (loop_file_fmt_drivers[drv->file_fmt_type] == NULL) { - loop_file_fmt_drivers[drv->file_fmt_type] = drv; - printk(KERN_INFO "loop_file_fmt: successfully registered file " + if (xloop_file_fmt_drivers[drv->file_fmt_type] == NULL) { + xloop_file_fmt_drivers[drv->file_fmt_type] = drv; + printk(KERN_INFO "xloop_file_fmt: successfully registered file " "format driver %s", drv->name); } else { - printk(KERN_WARNING "loop_file_fmt: driver for file format " + printk(KERN_WARNING "xloop_file_fmt: driver for file format " "already registered"); ret = -EBUSY; } return ret; } -EXPORT_SYMBOL(loop_file_fmt_register_driver); +EXPORT_SYMBOL(xloop_file_fmt_register_driver); -void loop_file_fmt_unregister_driver(struct loop_file_fmt_driver *drv) +void xloop_file_fmt_unregister_driver(struct xloop_file_fmt_driver *drv) { if (drv == NULL) return; - if (drv->file_fmt_type > MAX_LO_FILE_FMT) + if (drv->file_fmt_type > MAX_XLO_FILE_FMT) return; - loop_file_fmt_drivers[drv->file_fmt_type] = NULL; - printk(KERN_INFO "loop_file_fmt: successfully unregistered file " + xloop_file_fmt_drivers[drv->file_fmt_type] = NULL; + printk(KERN_INFO "xloop_file_fmt: successfully unregistered file " "format driver %s", drv->name); } -EXPORT_SYMBOL(loop_file_fmt_unregister_driver); +EXPORT_SYMBOL(xloop_file_fmt_unregister_driver); -struct loop_file_fmt *loop_file_fmt_alloc(void) +struct xloop_file_fmt *xloop_file_fmt_alloc(void) { - return kzalloc(sizeof(struct loop_file_fmt), GFP_KERNEL); + return kzalloc(sizeof(struct xloop_file_fmt), GFP_KERNEL); } -void loop_file_fmt_free(struct loop_file_fmt *lo_fmt) +void xloop_file_fmt_free(struct xloop_file_fmt *xlo_fmt) { - kfree(lo_fmt); + kfree(xlo_fmt); } -int loop_file_fmt_set_lo(struct loop_file_fmt *lo_fmt, struct loop_device *lo) +int xloop_file_fmt_set_xlo(struct xloop_file_fmt *xlo_fmt, struct xloop_device *xlo) { - if (lo_fmt == NULL) + if (xlo_fmt == NULL) return -EINVAL; - lo_fmt->lo = lo; + xlo_fmt->xlo = xlo; return 0; } -EXPORT_SYMBOL(loop_file_fmt_set_lo); +EXPORT_SYMBOL(xloop_file_fmt_set_xlo); -struct loop_device *loop_file_fmt_get_lo(struct loop_file_fmt *lo_fmt) +struct xloop_device *xloop_file_fmt_get_xlo(struct xloop_file_fmt *xlo_fmt) { - return lo_fmt->lo; + return xlo_fmt->xlo; } -EXPORT_SYMBOL(loop_file_fmt_get_lo); +EXPORT_SYMBOL(xloop_file_fmt_get_xlo); -int loop_file_fmt_init(struct loop_file_fmt *lo_fmt, +int xloop_file_fmt_init(struct xloop_file_fmt *xlo_fmt, u32 file_fmt_type) { - struct loop_file_fmt_ops *ops; + struct xloop_file_fmt_ops *ops; struct module *drv; int ret = 0; - if (file_fmt_type > MAX_LO_FILE_FMT) + if (file_fmt_type > MAX_XLO_FILE_FMT) return -EINVAL; - lo_fmt->file_fmt_type = file_fmt_type; + xlo_fmt->file_fmt_type = file_fmt_type; - if (lo_fmt->file_fmt_state != file_fmt_uninitialized) { - printk(KERN_WARNING "loop_file_fmt: file format is " + if (xlo_fmt->file_fmt_state != file_fmt_uninitialized) { + printk(KERN_WARNING "xloop_file_fmt: file format is " "initialized already"); return -EINVAL; } /* check if new file format driver is registered */ - if (loop_file_fmt_drivers[lo_fmt->file_fmt_type] == NULL) { - printk(KERN_ERR "loop_file_fmt: file format driver is not " + if (xloop_file_fmt_drivers[xlo_fmt->file_fmt_type] == NULL) { + printk(KERN_ERR "xloop_file_fmt: file format driver is not " "available"); return -ENODEV; } - printk(KERN_INFO "loop_file_fmt: use file format driver %s", - loop_file_fmt_drivers[lo_fmt->file_fmt_type]->name); + printk(KERN_INFO "xloop_file_fmt: use file format driver %s", + xloop_file_fmt_drivers[xlo_fmt->file_fmt_type]->name); - drv = loop_file_fmt_drivers[lo_fmt->file_fmt_type]->owner; + drv = xloop_file_fmt_drivers[xlo_fmt->file_fmt_type]->owner; if (!try_module_get(drv)) { - printk(KERN_ERR "loop_file_fmt: file format driver %s can not " + printk(KERN_ERR "xloop_file_fmt: file format driver %s can not " "be accessed", - loop_file_fmt_drivers[lo_fmt->file_fmt_type]->name); + xloop_file_fmt_drivers[xlo_fmt->file_fmt_type]->name); return -ENODEV; } - ops = loop_file_fmt_drivers[lo_fmt->file_fmt_type]->ops; + ops = xloop_file_fmt_drivers[xlo_fmt->file_fmt_type]->ops; if (likely(ops->init)) { - ret = ops->init(lo_fmt); + ret = ops->init(xlo_fmt); if (ret < 0) goto free_drv; } /* after increasing the refcount of file format driver module and * the successful initialization, the file format is initialized */ - lo_fmt->file_fmt_state = file_fmt_initialized; + xlo_fmt->file_fmt_state = file_fmt_initialized; return ret; free_drv: module_put(drv); - lo_fmt->file_fmt_state = file_fmt_uninitialized; + xlo_fmt->file_fmt_state = file_fmt_uninitialized; return ret; } -void loop_file_fmt_exit(struct loop_file_fmt *lo_fmt) +void xloop_file_fmt_exit(struct xloop_file_fmt *xlo_fmt) { - struct loop_file_fmt_ops *ops; + struct xloop_file_fmt_ops *ops; struct module *drv; - if (lo_fmt->file_fmt_state != file_fmt_initialized) { - printk(KERN_WARNING "loop_file_fmt: file format is " + if (xlo_fmt->file_fmt_state != file_fmt_initialized) { + printk(KERN_WARNING "xloop_file_fmt: file format is " "uninitialized already"); return; } - ops = loop_file_fmt_drivers[lo_fmt->file_fmt_type]->ops; + ops = xloop_file_fmt_drivers[xlo_fmt->file_fmt_type]->ops; if (likely(ops->exit)) - ops->exit(lo_fmt); + ops->exit(xlo_fmt); - drv = loop_file_fmt_drivers[lo_fmt->file_fmt_type]->owner; + drv = xloop_file_fmt_drivers[xlo_fmt->file_fmt_type]->owner; module_put(drv); /* after decreasing the refcount of file format driver module, * the file format is uninitialized */ - lo_fmt->file_fmt_state = file_fmt_uninitialized; + xlo_fmt->file_fmt_state = file_fmt_uninitialized; } -int loop_file_fmt_read(struct loop_file_fmt *lo_fmt, +int xloop_file_fmt_read(struct xloop_file_fmt *xlo_fmt, struct request *rq) { - struct loop_file_fmt_ops *ops; + struct xloop_file_fmt_ops *ops; - if (unlikely(lo_fmt->file_fmt_state != file_fmt_initialized)) { - printk(KERN_ERR "loop_file_fmt: file format is " + if (unlikely(xlo_fmt->file_fmt_state != file_fmt_initialized)) { + printk(KERN_ERR "xloop_file_fmt: file format is " "not initialized, can not read"); return -EINVAL; } - ops = loop_file_fmt_drivers[lo_fmt->file_fmt_type]->ops; + ops = xloop_file_fmt_drivers[xlo_fmt->file_fmt_type]->ops; if (likely(ops->read)) - return ops->read(lo_fmt, rq); + return ops->read(xlo_fmt, rq); else return -EIO; } -int loop_file_fmt_read_aio(struct loop_file_fmt *lo_fmt, +int xloop_file_fmt_read_aio(struct xloop_file_fmt *xlo_fmt, struct request *rq) { - struct loop_file_fmt_ops *ops; + struct xloop_file_fmt_ops *ops; - if (unlikely(lo_fmt->file_fmt_state != file_fmt_initialized)) { - printk(KERN_ERR "loop_file_fmt: file format is " + if (unlikely(xlo_fmt->file_fmt_state != file_fmt_initialized)) { + printk(KERN_ERR "xloop_file_fmt: file format is " "not initialized, can not read aio"); return -EINVAL; } - ops = loop_file_fmt_drivers[lo_fmt->file_fmt_type]->ops; + ops = xloop_file_fmt_drivers[xlo_fmt->file_fmt_type]->ops; if (likely(ops->read_aio)) - return ops->read_aio(lo_fmt, rq); + return ops->read_aio(xlo_fmt, rq); else return -EIO; } -int loop_file_fmt_write(struct loop_file_fmt *lo_fmt, +int xloop_file_fmt_write(struct xloop_file_fmt *xlo_fmt, struct request *rq) { - struct loop_file_fmt_ops *ops; + struct xloop_file_fmt_ops *ops; - if (unlikely(lo_fmt->file_fmt_state != file_fmt_initialized)) { - printk(KERN_ERR "loop_file_fmt: file format is " + if (unlikely(xlo_fmt->file_fmt_state != file_fmt_initialized)) { + printk(KERN_ERR "xloop_file_fmt: file format is " "not initialized, can not write"); return -EINVAL; } - ops = loop_file_fmt_drivers[lo_fmt->file_fmt_type]->ops; + ops = xloop_file_fmt_drivers[xlo_fmt->file_fmt_type]->ops; if (likely(ops->write)) - return ops->write(lo_fmt, rq); + return ops->write(xlo_fmt, rq); else return -EIO; } -int loop_file_fmt_write_aio(struct loop_file_fmt *lo_fmt, +int xloop_file_fmt_write_aio(struct xloop_file_fmt *xlo_fmt, struct request *rq) { - struct loop_file_fmt_ops *ops; + struct xloop_file_fmt_ops *ops; - if (unlikely(lo_fmt->file_fmt_state != file_fmt_initialized)) { - printk(KERN_ERR "loop_file_fmt: file format is " + if (unlikely(xlo_fmt->file_fmt_state != file_fmt_initialized)) { + printk(KERN_ERR "xloop_file_fmt: file format is " "not initialized, can not write aio"); return -EINVAL; } - ops = loop_file_fmt_drivers[lo_fmt->file_fmt_type]->ops; + ops = xloop_file_fmt_drivers[xlo_fmt->file_fmt_type]->ops; if (likely(ops->write_aio)) - return ops->write_aio(lo_fmt, rq); + return ops->write_aio(xlo_fmt, rq); else return -EIO; } -int loop_file_fmt_discard(struct loop_file_fmt *lo_fmt, +int xloop_file_fmt_write_zeros(struct xloop_file_fmt *xlo_fmt, struct request *rq) { - struct loop_file_fmt_ops *ops; + struct xloop_file_fmt_ops *ops; - if (unlikely(lo_fmt->file_fmt_state != file_fmt_initialized)) { - printk(KERN_ERR "loop_file_fmt: file format is " + if (unlikely(xlo_fmt->file_fmt_state != file_fmt_initialized)) { + printk(KERN_ERR "xloop_file_fmt: file format is " + "not initialized, can not write zeros"); + return -EINVAL; + } + + ops = xloop_file_fmt_drivers[xlo_fmt->file_fmt_type]->ops; + if (likely(ops->write_zeros)) + return ops->write_zeros(xlo_fmt, rq); + else + return -EIO; +} + +int xloop_file_fmt_discard(struct xloop_file_fmt *xlo_fmt, + struct request *rq) +{ + struct xloop_file_fmt_ops *ops; + + if (unlikely(xlo_fmt->file_fmt_state != file_fmt_initialized)) { + printk(KERN_ERR "xloop_file_fmt: file format is " "not initialized, can not discard"); return -EINVAL; } - ops = loop_file_fmt_drivers[lo_fmt->file_fmt_type]->ops; + ops = xloop_file_fmt_drivers[xlo_fmt->file_fmt_type]->ops; if (likely(ops->discard)) - return ops->discard(lo_fmt, rq); + return ops->discard(xlo_fmt, rq); else return -EIO; } -int loop_file_fmt_flush(struct loop_file_fmt *lo_fmt) +int xloop_file_fmt_flush(struct xloop_file_fmt *xlo_fmt) { - struct loop_file_fmt_ops *ops; + struct xloop_file_fmt_ops *ops; - if (unlikely(lo_fmt->file_fmt_state != file_fmt_initialized)) { - printk(KERN_ERR "loop_file_fmt: file format is " + if (unlikely(xlo_fmt->file_fmt_state != file_fmt_initialized)) { + printk(KERN_ERR "xloop_file_fmt: file format is " "not initialized, can not flush"); return -EINVAL; } - ops = loop_file_fmt_drivers[lo_fmt->file_fmt_type]->ops; + ops = xloop_file_fmt_drivers[xlo_fmt->file_fmt_type]->ops; if (likely(ops->flush)) - return ops->flush(lo_fmt); + return ops->flush(xlo_fmt); return 0; } -loff_t loop_file_fmt_sector_size(struct loop_file_fmt *lo_fmt) +loff_t xloop_file_fmt_sector_size(struct xloop_file_fmt *xlo_fmt, + struct file *file, loff_t offset, loff_t sizelimit) { - struct loop_file_fmt_ops *ops; + struct xloop_file_fmt_ops *ops; - if (unlikely(lo_fmt->file_fmt_state != file_fmt_initialized)) { - printk(KERN_ERR "loop_file_fmt: file format is " + if (unlikely(xlo_fmt->file_fmt_state != file_fmt_initialized)) { + printk(KERN_ERR "xloop_file_fmt: file format is " "not initialized, can not read sector size"); return 0; } - ops = loop_file_fmt_drivers[lo_fmt->file_fmt_type]->ops; + ops = xloop_file_fmt_drivers[xlo_fmt->file_fmt_type]->ops; if (likely(ops->sector_size)) - return ops->sector_size(lo_fmt); + return ops->sector_size(xlo_fmt, file, offset, sizelimit); else return 0; } -int loop_file_fmt_change(struct loop_file_fmt *lo_fmt, +int xloop_file_fmt_change(struct xloop_file_fmt *xlo_fmt, u32 file_fmt_type_new) { - if (file_fmt_type_new > MAX_LO_FILE_FMT) + if (file_fmt_type_new > MAX_XLO_FILE_FMT) return -EINVAL; /* Unload the old file format driver if the file format is * initialized */ - if (lo_fmt->file_fmt_state == file_fmt_initialized) - loop_file_fmt_exit(lo_fmt); + if (xlo_fmt->file_fmt_state == file_fmt_initialized) + xloop_file_fmt_exit(xlo_fmt); /* Load the new file format driver because the file format is * uninitialized now */ - return loop_file_fmt_init(lo_fmt, file_fmt_type_new); + return xloop_file_fmt_init(xlo_fmt, file_fmt_type_new); } -ssize_t loop_file_fmt_print_type(u32 file_fmt_type, char *file_fmt_name) +ssize_t xloop_file_fmt_print_type(u32 file_fmt_type, char *file_fmt_name) { ssize_t len = 0; switch (file_fmt_type) { - case LO_FILE_FMT_RAW: + case XLO_FILE_FMT_RAW: len = sprintf(file_fmt_name, "%s", "RAW"); break; - case LO_FILE_FMT_QCOW: + case XLO_FILE_FMT_QCOW: len = sprintf(file_fmt_name, "%s", "QCOW"); break; - case LO_FILE_FMT_VDI: + case XLO_FILE_FMT_VDI: len = sprintf(file_fmt_name, "%s", "VDI"); break; - case LO_FILE_FMT_VMDK: + case XLO_FILE_FMT_VMDK: len = sprintf(file_fmt_name, "%s", "VMDK"); break; default: - len = sprintf(file_fmt_name, "%s", "ERROR: Unsupported loop " + len = sprintf(file_fmt_name, "%s", "ERROR: Unsupported xloop " "file format!"); break; } return len; } -EXPORT_SYMBOL(loop_file_fmt_print_type); +EXPORT_SYMBOL(xloop_file_fmt_print_type); |