From 43e57ce5e11e9052f5a7db66f2e8613f1784f919 Mon Sep 17 00:00:00 2001 From: Frederic Robra Date: Tue, 25 Jun 2019 17:03:28 +0200 Subject: first version of dnbd3-ng --- src/kernel/core.c | 484 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/kernel/dnbd3.h | 86 ++++++++++ src/kernel/sysfs.c | 205 +++++++++++++++++++++++ src/kernel/sysfs.h | 45 +++++ src/kernel/utils.c | 41 +++++ src/kernel/utils.h | 29 ++++ 6 files changed, 890 insertions(+) create mode 100644 src/kernel/core.c create mode 100644 src/kernel/dnbd3.h create mode 100644 src/kernel/sysfs.c create mode 100644 src/kernel/sysfs.h create mode 100644 src/kernel/utils.c create mode 100644 src/kernel/utils.h (limited to 'src/kernel') diff --git a/src/kernel/core.c b/src/kernel/core.c new file mode 100644 index 0000000..bfa8d22 --- /dev/null +++ b/src/kernel/core.c @@ -0,0 +1,484 @@ +/* + * This file is part of the Distributed Network Block Device 3 + * + * Copyright(c) 2019 Frederic Robra + * Parts copyright 2011-2012 Johann Latocha + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "dnbd3.h" +#include "clientconfig.h" +#include "sysfs.h" + +static DEFINE_IDR(dnbd3_index_idr); +static DEFINE_MUTEX(dnbd3_index_mutex); + +static unsigned int max_devs = NUMBER_DEVICES; +static dnbd3_device_t *dnbd3_device; +int major; + + +static int dnbd3_open(struct block_device *bdev, fmode_t mode) +{ + printk(KERN_DEBUG "dnbd3: dnbd3_open"); + + return 0; +} + +static void dnbd3_release(struct gendisk *disk, fmode_t mode) +{ + printk(KERN_DEBUG "dnbd3: dnbd3_release"); + +} + + +void dnbd3_blk_fail_all_requests(dnbd3_device_t *dev) +{ + printk(KERN_DEBUG "dnbd3: dnbd3_blk_fail_all_requests"); +} + + +int dnbd3_net_connect(dnbd3_device_t *dev) +{ + return 0; +} + + +int dnbd3_net_disconnect(dnbd3_device_t *dev) +{ + return 0; +} + +static int dnbd3_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) +{ + printk(KERN_DEBUG "dnbd3: dnbd3_ioctl"); + + int result = -100; + dnbd3_device_t *dev = bdev->bd_disk->private_data; + char *imgname = NULL; + dnbd3_ioctl_t *msg = NULL; + //unsigned long irqflags; + + while (dev->disconnecting) + { + // do nothing + } + + if (arg != 0) + { + msg = kmalloc(sizeof(*msg), GFP_KERNEL); + if (msg == NULL) return -ENOMEM; + if (copy_from_user((char *)msg, (char *)arg, 2) != 0 || msg->len != sizeof(*msg)) + { + result = -ENOEXEC; + goto cleanup_return; + } + if (copy_from_user((char *)msg, (char *)arg, sizeof(*msg)) != 0) + { + result = -ENOENT; + goto cleanup_return; + } + if (msg->imgname != NULL && msg->imgnamelen > 0) + { + imgname = kmalloc(msg->imgnamelen + 1, GFP_KERNEL); + if (imgname == NULL) + { + result = -ENOMEM; + goto cleanup_return; + } + if (copy_from_user(imgname, msg->imgname, msg->imgnamelen) != 0) + { + result = -ENOENT; + goto cleanup_return; + } + imgname[msg->imgnamelen] = '\0'; + //printk("IOCTL Image name of len %d is %s\n", (int)msg->imgnamelen, imgname); + } + } + + + switch (cmd) + { + case IOCTL_OPEN: + if (dev->imgname != NULL) + { + result = -EBUSY; + } + else if (imgname == NULL) + { + result = -EINVAL; + } + else if (msg == NULL) + { + result = -EINVAL; + } + else + { + if (sizeof(msg->host) != sizeof(dev->cur_server.host)) + printk("Odd size bug#1 triggered in IOCTL\n"); + memcpy(&dev->cur_server.host, &msg->host, sizeof(msg->host)); + dev->cur_server.failures = 0; + memcpy(&dev->initial_server, &dev->cur_server, sizeof(dev->initial_server)); + dev->imgname = imgname; + dev->rid = msg->rid; + dev->use_server_provided_alts = msg->use_server_provided_alts; + // Forget all alt servers on explicit connect, set first al server to initial server + memset(dev->alt_servers, 0, sizeof(dev->alt_servers[0])*NUMBER_SERVERS); + memcpy(dev->alt_servers, &dev->initial_server, sizeof(dev->alt_servers[0])); +//#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) +// if (blk_queue->backing_dev_info != NULL) { +// blk_queue->backing_dev_info->ra_pages = (msg->read_ahead_kb * 1024) / PAGE_SIZE; +// } +//#else +// blk_queue->backing_dev_info.ra_pages = (msg->read_ahead_kb * 1024) / PAGE_SIZE; +//#endif + if (dnbd3_net_connect(dev) == 0) + { + result = 0; + imgname = NULL; // Prevent kfree at the end + } + else + { + result = -ENOENT; + dev->imgname = NULL; + } + } + break; + + case IOCTL_CLOSE: + dnbd3_blk_fail_all_requests(dev); + result = dnbd3_net_disconnect(dev); + dnbd3_blk_fail_all_requests(dev); + set_capacity(dev->disk, 0); + if (dev->imgname) + { + kfree(dev->imgname); + dev->imgname = NULL; + } + break; + + case IOCTL_SWITCH: + result = -EINVAL; + break; + + case IOCTL_ADD_SRV: + case IOCTL_REM_SRV: + if (dev->imgname == NULL) + { + result = -ENOENT; + } + else if (dev->new_servers_num >= NUMBER_SERVERS) + { + result = -EAGAIN; + } + else if (msg == NULL) + { + result = -EINVAL; + } + else + { + memcpy(&dev->new_servers[dev->new_servers_num].host, &msg->host, sizeof(msg->host)); + dev->new_servers[dev->new_servers_num].failures = (cmd == IOCTL_ADD_SRV ? 0 : 1); // 0 = ADD, 1 = REM + ++dev->new_servers_num; + result = 0; + } + break; + + case BLKFLSBUF: + result = 0; + break; + + default: + result = -EIO; + break; + } + +cleanup_return: + if (msg) kfree(msg); + if (imgname) kfree(imgname); + return result; + +} + +static const struct block_device_operations dnbd3_fops = +{ + .owner = THIS_MODULE, + .open = dnbd3_open, + .release = dnbd3_release, + .ioctl = dnbd3_ioctl, + .compat_ioctl = dnbd3_ioctl, +}; + +static blk_status_t dnbd3_queue_rq(struct blk_mq_hw_ctx *hctx, const struct blk_mq_queue_data *bd) +{ + printk(KERN_DEBUG "dnbd3: dnbd3_queue_rq"); + return 0; +} + +static void dnbd3_complete_rq(struct request *req) +{ + printk(KERN_DEBUG "dnbd3: dnbd3_complete_rq"); + +} + +static int dnbd3_init_request(struct blk_mq_tag_set *set, struct request *rq, unsigned int hctx_idx, unsigned int numa_node) +{ + struct dnbd3_cmd *cmd = blk_mq_rq_to_pdu(rq); + cmd->dnbd3 = set->driver_data; + cmd->flags = 0; + mutex_init(&cmd->lock); + return 0; +} +static enum blk_eh_timer_return dnbd3_xmit_timeout(struct request *req, bool reserved) +{ + printk(KERN_DEBUG "dnbd3: dnbd3_xmit_timeout"); + return BLK_EH_DONE; +} + + +static const struct blk_mq_ops dnbd3_mq_ops = { + .queue_rq = dnbd3_queue_rq, + .complete = dnbd3_complete_rq, + .init_request = dnbd3_init_request, + .timeout = dnbd3_xmit_timeout, +}; + + +static int dnbd3_blk_add_device(dnbd3_device_t *dev, int minor) +{ + struct gendisk *disk; + struct request_queue *q; + int err = -ENOMEM; + printk(KERN_DEBUG "dnbd3: adding device %i", minor); + + + disk = alloc_disk(1); + if (!disk) { + printk(KERN_DEBUG "dnbd3: alloc_disc failed, device %i", minor); + goto out_free_nbd; + } + + err = idr_alloc(&dnbd3_index_idr, dev, minor, minor + 1, GFP_KERNEL); + if (err == -ENOSPC) { + printk(KERN_DEBUG "dnbd3: idr_alloc failed, device %i", minor); + err = -EEXIST; + } + + if (err < 0) + goto out_free_disk; + + dev->minor = minor; + dev->disk = disk; + dev->tag_set.ops = &dnbd3_mq_ops; + dev->tag_set.nr_hw_queues = 1; + dev->tag_set.queue_depth = 128; + dev->tag_set.numa_node = NUMA_NO_NODE; + dev->tag_set.cmd_size = sizeof(dnbd3_cmd); + dev->tag_set.flags = BLK_MQ_F_SHOULD_MERGE | + BLK_MQ_F_SG_MERGE | BLK_MQ_F_BLOCKING; + dev->tag_set.driver_data = dev; + + err = blk_mq_alloc_tag_set(&dev->tag_set); + if (err) + goto out_free_idr; + + q = blk_mq_init_queue(&dev->tag_set); + if (IS_ERR(q)) { + err = PTR_ERR(q); + goto out_free_tags; + } + disk->queue = q; + + /* + * Tell the block layer that we are not a rotational device + */ + blk_queue_flag_set(QUEUE_FLAG_NONROT, disk->queue); + blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, disk->queue); + disk->queue->limits.discard_granularity = 0; + disk->queue->limits.discard_alignment = 0; + blk_queue_max_discard_sectors(disk->queue, 0); + blk_queue_max_segment_size(disk->queue, UINT_MAX); + blk_queue_max_segments(disk->queue, USHRT_MAX); + blk_queue_max_hw_sectors(disk->queue, 65536); + disk->queue->limits.max_sectors = 256; + + mutex_init(&dev->config_lock); + refcount_set(&dev->config_refs, 0); + refcount_set(&dev->refs, 1); + INIT_LIST_HEAD(&dev->list); + disk->major = major; + disk->first_minor = minor; + disk->fops = &dnbd3_fops; + disk->private_data = dev; + sprintf(disk->disk_name, "dnbd%d", minor); +// sprintf(disk->disk_name, "dnbd3%d", minor); + printk(KERN_DEBUG "dnbd3: add disk, device %s", disk->disk_name); + add_disk(disk); + dnbd3_sysfs_init(dev); + return minor; + +out_free_tags: + blk_mq_free_tag_set(&dev->tag_set); +out_free_idr: + idr_remove(&dnbd3_index_idr, minor); +out_free_disk: + put_disk(disk); +out_free_nbd: + kfree(dev); + printk(KERN_DEBUG "dnbd3: destroy device %i", minor); + return err; +} + + + +static int __init dnbd3_init(void) +{ + int i; + printk(KERN_DEBUG "dnbd3: starting kernel module"); + + if (max_devs < 0) { + printk(KERN_ERR "dnbd3: max_devs must be >= 0"); + return -EINVAL; + } + + + dnbd3_device = kcalloc(max_devs, sizeof(*dnbd3_device), GFP_KERNEL); + if (!dnbd3_device) { + printk(KERN_ERR "dnbd3: failed to create dnbd3 device"); + return -ENOMEM; + } + + // initialize block device + major = register_blkdev(0, "dnbd3"); + if (major == 0) { + printk(KERN_ERR "dnbd3: register_blkdev failed"); + return -EIO; + } + + printk(KERN_DEBUG "dnbd3: kernel module loaded. Machine type: " ENDIAN_MODE); + + // add MAX_NUMBER_DEVICES devices + mutex_lock(&dnbd3_index_mutex); + for (i = 0; i < max_devs; i++) { + dnbd3_blk_add_device(&dnbd3_device[i], i); + } + mutex_unlock(&dnbd3_index_mutex); + + printk(KERN_INFO "dnbd3: init successful (%i devices).\n", max_devs); + + return 0; +} + + +static int dnbd3_exit_cb(int id, void *ptr, void *data) +{ + struct list_head *list = (struct list_head *)data; + struct dnbd3_device_t *dnbd3 = ptr; + + list_add_tail(&dnbd3->list, list); + return 0; +} + +static void dnbd3_dev_remove(struct dnbd3_device_t *dnbd3) +{ + struct gendisk *disk = dnbd3->disk; + struct request_queue *q; + + if (disk) { + q = disk->queue; + del_gendisk(disk); + blk_cleanup_queue(q); + blk_mq_free_tag_set(&dnbd3->tag_set); + disk->private_data = NULL; + put_disk(disk); + } +} + +static void dnbd3_put(struct dnbd3_device_t *dnbd3) +{ + if (refcount_dec_and_mutex_lock(&dnbd3->refs, &dnbd3_index_mutex)) { + idr_remove(&dnbd3_index_idr, dnbd3->minor); + mutex_unlock(&dnbd3_index_mutex); + dnbd3_dev_remove(dnbd3); + } +} + + +static void __exit dnbd3_exit(void) +{ + dnbd3_device_t *dnbd3; + LIST_HEAD(del_list); + printk(KERN_DEBUG "dnbd3: stopping kernel module"); + + mutex_lock(&dnbd3_index_mutex); + idr_for_each(&dnbd3_index_idr, &dnbd3_exit_cb, &del_list); + mutex_unlock(&dnbd3_index_mutex); + + while (!list_empty(&del_list)) { + dnbd3 = list_first_entry(&del_list, struct dnbd3_device_t, list); + dnbd3_sysfs_exit(dnbd3); + list_del_init(&dnbd3->list); + if (refcount_read(&dnbd3->refs) != 1) { + printk(KERN_ERR "dnbd3: possibly leaking a device\n"); + } + dnbd3_put(dnbd3); + } + + idr_destroy(&dnbd3_index_idr); + unregister_blkdev(major, "dnbd3"); + + kfree(dnbd3_device); + + printk(KERN_INFO "dnbd3: stopped kernel module"); +} + + +module_init(dnbd3_init); +module_exit(dnbd3_exit); + +MODULE_DESCRIPTION("Distributed Network Block Device 3"); +MODULE_LICENSE("GPL"); + +module_param(max_devs, int, 0444); +MODULE_PARM_DESC(max_devs, "number of network block devices to initialize (default: 8)"); diff --git a/src/kernel/dnbd3.h b/src/kernel/dnbd3.h new file mode 100644 index 0000000..2575cd8 --- /dev/null +++ b/src/kernel/dnbd3.h @@ -0,0 +1,86 @@ +/* + * This file is part of the Distributed Network Block Device 3 + * + * Copyright(c) 2019 Frederic Robra + * Parts copyright 2011-2012 Johann Latocha + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ +#ifndef DNBD_H_ +#define DNBD_H_ + +#include +#include +#include +#include + +#define KERNEL_MODULE +#include "types.h" + +typedef struct +{ + dnbd3_host_t host; + uint64_t rtts[4]; // Last four round trip time measurements in microsecond + uint16_t protocol_version; // dnbd3 protocol version of this server + uint8_t failures; // How many times the server was unreachable +} dnbd3_server_t; + + +typedef struct dnbd3_device_t { + int minor; + struct blk_mq_tag_set tag_set; + struct request_queue queue; + struct mutex config_lock; + refcount_t config_refs; + refcount_t refs; + struct list_head list; + + // block + struct gendisk *disk; + + // sysfs + struct kobject kobj; + + // network + char *imgname; + struct socket *sock; + dnbd3_server_t cur_server, initial_server; + unsigned long cur_rtt; +// serialized_buffer_t payload_buffer; + dnbd3_server_t alt_servers[NUMBER_SERVERS]; // array of alt servers + int new_servers_num; // number of new alt servers that are waiting to be copied to above array + dnbd3_server_entry_t new_servers[NUMBER_SERVERS]; // pending new alt servers + uint8_t discover, panic, disconnecting, update_available, panic_count; + uint8_t use_server_provided_alts; + uint16_t rid; + uint32_t heartbeat_count; + uint64_t reported_size; + // server switch + struct socket *better_sock; + +} dnbd3_device_t; + + +typedef struct dnbd3_cmd { + struct dnbd3_device_t *dnbd3; + struct mutex lock; + int index; + int cookie; + blk_status_t status; + unsigned long flags; + u32 cmd_cookie; +} dnbd3_cmd; + +#endif /* DNBD_H_ */ diff --git a/src/kernel/sysfs.c b/src/kernel/sysfs.c new file mode 100644 index 0000000..4406072 --- /dev/null +++ b/src/kernel/sysfs.c @@ -0,0 +1,205 @@ +/* + * This file is part of the Distributed Network Block Device 3 + * + * Copyright(c) 2011-2012 Johann Latocha + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include + +#include "sysfs.h" +#include "utils.h" + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +ssize_t show_cur_server_addr(char *buf, dnbd3_device_t *dev) +{ + if (dev->cur_server.host.type == HOST_IP4) + return MIN(snprintf(buf, PAGE_SIZE, "%pI4,%d\n", dev->cur_server.host.addr, (int)ntohs(dev->cur_server.host.port)), PAGE_SIZE); + else if (dev->cur_server.host.type == HOST_IP6) + return MIN(snprintf(buf, PAGE_SIZE, "%pI6,%d\n", dev->cur_server.host.addr, (int)ntohs(dev->cur_server.host.port)), PAGE_SIZE); + *buf = '\0'; + return 0; +} + +ssize_t show_cur_server_rtt(char *buf, dnbd3_device_t *dev) +{ + return MIN(snprintf(buf, PAGE_SIZE, "%llu\n", (unsigned long long)dev->cur_rtt), PAGE_SIZE); +} + +ssize_t show_alt_server_num(char *buf, dnbd3_device_t *dev) +{ + int i, num = 0; + for (i = 0; i < NUMBER_SERVERS; ++i) + { + if (dev->alt_servers[i].host.type) ++num; + } + return MIN(snprintf(buf, PAGE_SIZE, "%d\n", num), PAGE_SIZE); +} + +ssize_t show_alt_servers(char *buf, dnbd3_device_t *dev) +{ + int i, size = PAGE_SIZE, ret; + for (i = 0; i < NUMBER_SERVERS; ++i) + { + if (dev->alt_servers[i].host.type == HOST_IP4) + ret = MIN(snprintf(buf, size, "%pI4,%d,%llu,%d\n", + dev->alt_servers[i].host.addr, + (int)ntohs(dev->alt_servers[i].host.port), + (unsigned long long)((dev->alt_servers[i].rtts[0] + dev->alt_servers[i].rtts[1] + dev->alt_servers[i].rtts[2] + dev->alt_servers[i].rtts[3]) / 4), + (int)dev->alt_servers[i].failures) + , size); + else if (dev->alt_servers[i].host.type == HOST_IP6) + ret = MIN(snprintf(buf, size, "%pI6,%d,%llu,%d\n", + dev->alt_servers[i].host.addr, + (int)ntohs(dev->alt_servers[i].host.port), + (unsigned long long)((dev->alt_servers[i].rtts[0] + dev->alt_servers[i].rtts[1] + dev->alt_servers[i].rtts[2] + dev->alt_servers[i].rtts[3]) / 4), + (int)dev->alt_servers[i].failures) + , size); + else + continue; + size -= ret; + buf += ret; + if (size <= 0) + { + size = 0; + break; + } + } + return PAGE_SIZE - size; +} + +ssize_t show_image_name(char *buf, dnbd3_device_t *dev) +{ + if (dev->imgname == NULL) return sprintf(buf, "(null)"); + return MIN(snprintf(buf, PAGE_SIZE, "%s\n", dev->imgname), PAGE_SIZE); +} + +ssize_t show_rid(char *buf, dnbd3_device_t *dev) +{ + return MIN(snprintf(buf, PAGE_SIZE, "%d\n", dev->rid), PAGE_SIZE); +} + +ssize_t show_update_available(char *buf, dnbd3_device_t *dev) +{ + return MIN(snprintf(buf, PAGE_SIZE, "%d\n", dev->update_available), PAGE_SIZE); +} + +device_attr_t cur_server_addr = +{ + .attr = {.name = "cur_server_addr", .mode = 0444 }, + .show = show_cur_server_addr, + .store = NULL, +}; + +device_attr_t cur_server_rtt = +{ + .attr = {.name = "cur_server_rtt", .mode = 0444 }, + .show = show_cur_server_rtt, + .store = NULL, +}; + +device_attr_t alt_server_num = +{ + .attr = {.name = "alt_server_num", .mode = 0444 }, + .show = show_alt_server_num, + .store = NULL, +}; + +device_attr_t alt_servers = +{ + .attr = {.name = "alt_servers", .mode = 0444 }, + .show = show_alt_servers, + .store = NULL, +}; + +device_attr_t image_name = +{ + .attr = {.name = "image_name", .mode = 0444 }, + .show = show_image_name, + .store = NULL, +}; + +device_attr_t rid = +{ + .attr = {.name = "rid", .mode = 0444 }, + .show = show_rid, + .store = NULL, +}; + +device_attr_t update_available = +{ + .attr = {.name = "update_available", .mode = 0444 }, + .show = show_update_available, + .store = NULL, +}; + +ssize_t device_show(struct kobject *kobj, struct attribute *attr, char *buf) +{ + device_attr_t *device_attr = container_of(attr, device_attr_t, attr); + dnbd3_device_t *dev = container_of(kobj, dnbd3_device_t, kobj); + return device_attr->show(buf, dev); +} + +struct attribute *device_attrs[] = +{ + &cur_server_addr.attr, + &cur_server_rtt.attr, + &alt_server_num.attr, + &alt_servers.attr, + &image_name.attr, + &rid.attr, + &update_available.attr, + NULL, +}; + + +struct sysfs_ops device_ops = +{ + .show = device_show, +}; + +void release(struct kobject *kobj) +{ + kobj->state_initialized = 0; +} + +struct kobj_type device_ktype = +{ + .default_attrs = device_attrs, + .sysfs_ops = &device_ops, + .release = release, +}; + + +void dnbd3_sysfs_init(dnbd3_device_t *dev) +{ + int error; + struct kobject *kobj = &dev->kobj; + struct kobj_type *ktype = &device_ktype; + struct kobject *parent = &disk_to_dev(dev->disk)->kobj; + + error = kobject_init_and_add(kobj, ktype, parent, "%s", "net"); + if (error) + printk("Error initializing dnbd3 device!\n"); +} + +void dnbd3_sysfs_exit(dnbd3_device_t *dev) +{ + kobject_put(&dev->kobj); +} diff --git a/src/kernel/sysfs.h b/src/kernel/sysfs.h new file mode 100644 index 0000000..0a747a5 --- /dev/null +++ b/src/kernel/sysfs.h @@ -0,0 +1,45 @@ +/* + * This file is part of the Distributed Network Block Device 3 + * + * Copyright(c) 2011-2012 Johann Latocha + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef SYSFS_H_ +#define SYSFS_H_ + +#include "dnbd3.h" + +void dnbd3_sysfs_init(dnbd3_device_t *dev); + +void dnbd3_sysfs_exit(dnbd3_device_t *dev); + +typedef struct +{ + struct attribute attr; + ssize_t (*show)(char *, dnbd3_device_t *); + ssize_t (*store)(const char *, size_t, dnbd3_device_t *); +} device_attr_t; + +typedef struct +{ + struct attribute attr; + ssize_t (*show)(char *, dnbd3_server_t *); + ssize_t (*store)(const char *, size_t, dnbd3_server_t *); +} server_attr_t; + + +#endif /* SYSFS_H_ */ diff --git a/src/kernel/utils.c b/src/kernel/utils.c new file mode 100644 index 0000000..902025f --- /dev/null +++ b/src/kernel/utils.c @@ -0,0 +1,41 @@ +/* + * This file is part of the Distributed Network Block Device 3 + * + * Copyright(c) 2011-2012 Johann Latocha + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include + +#include "utils.h" + +unsigned int inet_addr(char *str) +{ + int a, b, c, d; + char arr[4]; + sscanf(str, "%d.%d.%d.%d", &a, &b, &c, &d); + arr[0] = a; + arr[1] = b; + arr[2] = c; + arr[3] = d; + return *(unsigned int *) arr; +} + +void inet_ntoa(struct in_addr addr, char *str) +{ + unsigned char *ptr = (unsigned char *) &addr; + sprintf(str, "%d.%d.%d.%d", ptr[0] & 0xff, ptr[1] & 0xff, ptr[2] & 0xff, ptr[3] & 0xff); +} diff --git a/src/kernel/utils.h b/src/kernel/utils.h new file mode 100644 index 0000000..e54b3cf --- /dev/null +++ b/src/kernel/utils.h @@ -0,0 +1,29 @@ +/* + * This file is part of the Distributed Network Block Device 3 + * + * Copyright(c) 2011-2012 Johann Latocha + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef UTILS_H_ +#define UTILS_H_ + +#include + +unsigned int inet_addr(char *str); +void inet_ntoa(struct in_addr addr, char *str); + +#endif /* UTILS_H_ */ -- cgit v1.2.3-55-g7522