diff --git a/modules/cas_cache/cas_cache.h b/modules/cas_cache/cas_cache.h index 23b3eb4..ac27681 100644 --- a/modules/cas_cache/cas_cache.h +++ b/modules/cas_cache/cas_cache.h @@ -51,15 +51,11 @@ enum { }; struct cas_module { - struct list_head disk_list; - uint32_t next_disk_id; int disk_major; int next_minor; struct kmem_cache *disk_cache; struct kmem_cache *exp_obj_cache; - - struct kobject kobj; }; extern struct cas_module cas_module; diff --git a/modules/cas_cache/disk.c b/modules/cas_cache/disk.c index 37d38db..1738802 100644 --- a/modules/cas_cache/disk.c +++ b/modules/cas_cache/disk.c @@ -13,11 +13,6 @@ #define CAS_DISK_OPEN_FMODE (FMODE_READ | FMODE_WRITE) -static inline struct cas_disk *cas_kobj_to_disk(struct kobject *kobj) -{ - return container_of(kobj, struct cas_disk, kobj); -} - static inline struct block_device *open_bdev_exclusive(const char *path, fmode_t mode, void *holder) @@ -30,48 +25,15 @@ static inline void close_bdev_exclusive(struct block_device *bdev, fmode_t mode) blkdev_put(bdev, mode | FMODE_EXCL); } -static void _cas_disk_release(struct kobject *kobj) -{ - struct cas_disk *dsk; - - BUG_ON(!kobj); - - dsk = cas_kobj_to_disk(kobj); - BUG_ON(!dsk); - - CAS_DEBUG_DISK_TRACE(dsk); - - kfree(dsk->path); - - kmem_cache_free(cas_module.disk_cache, dsk); -} - -static struct kobj_type cas_disk_ktype = { - .release = _cas_disk_release, -}; - int __init cas_init_disks(void) { CAS_DEBUG_TRACE(); - cas_module.next_disk_id = 1; - INIT_LIST_HEAD(&cas_module.disk_list); - - cas_module.disk_major = register_blkdev(cas_module.disk_major, - "cas"); - if (cas_module.disk_major <= 0) { - CAS_DEBUG_ERROR("Cannot allocate major number"); - return -EINVAL; - } - CAS_DEBUG_PARAM("Allocated major number: %d", cas_module.disk_major); - cas_module.disk_cache = kmem_cache_create("cas_disk", sizeof(struct cas_disk), 0, 0, NULL); - if (!cas_module.disk_cache) { - unregister_blkdev(cas_module.disk_major, "cas"); + if (!cas_module.disk_cache) return -ENOMEM; - } return 0; } @@ -81,23 +43,9 @@ void cas_deinit_disks(void) CAS_DEBUG_TRACE(); kmem_cache_destroy(cas_module.disk_cache); - unregister_blkdev(cas_module.disk_major, "cas"); } -static int _cas_disk_init_kobject(struct cas_disk *dsk) -{ - int result = 0; - - kobject_init(&dsk->kobj, &cas_disk_ktype); - result = kobject_add(&dsk->kobj, &disk_to_dev(dsk->bd->bd_disk)->kobj, - "cas%d", dsk->id); - if (result) - CAS_DEBUG_DISK_ERROR(dsk, "Cannot register kobject"); - - return result; -} - -struct cas_disk *cas_disk_open(const char *path, void *private) +struct cas_disk *cas_disk_open(const char *path) { struct cas_disk *dsk; int result = 0; @@ -113,8 +61,6 @@ struct cas_disk *cas_disk_open(const char *path, void *private) goto error_kmem; } - mutex_init(&dsk->openers_lock); - dsk->path = kstrdup(path, GFP_KERNEL); if (!dsk->path) { result = -ENOMEM; @@ -128,22 +74,10 @@ struct cas_disk *cas_disk_open(const char *path, void *private) goto error_open_bdev; } - dsk->private = private; - - dsk->id = cas_module.next_disk_id++; - list_add(&dsk->list, &cas_module.disk_list); - - result = _cas_disk_init_kobject(dsk); - if (result) - goto error_kobject; - CAS_DEBUG_DISK(dsk, "Created (%p)", dsk); return dsk; -error_kobject: - list_del(&dsk->list); - close_bdev_exclusive(dsk->bd, CAS_DISK_OPEN_FMODE); error_open_bdev: kfree(dsk->path); error_kstrdup: @@ -152,36 +86,6 @@ error_kmem: return ERR_PTR(result); } -static void _cas_disk_claim(struct cas_disk *dsk, void *private) -{ - dsk->private = private; -} - -struct cas_disk *cas_disk_claim(const char *path, void *private) -{ - struct list_head *item; - struct cas_disk *dsk = NULL; - - BUG_ON(!path); - - list_for_each(item, &cas_module.disk_list) { - dsk = list_entry(item, struct cas_disk, list); - if (strncmp(path, dsk->path, PATH_MAX) == 0) { - _cas_disk_claim(dsk, private); - return dsk; - } - } - return NULL; -} - -static void __cas_disk_close(struct cas_disk *dsk) -{ - close_bdev_exclusive(dsk->bd, CAS_DISK_OPEN_FMODE); - - cas_exp_obj_free(dsk); - kobject_put(&dsk->kobj); -} - void cas_disk_close(struct cas_disk *dsk) { BUG_ON(!dsk); @@ -189,9 +93,10 @@ void cas_disk_close(struct cas_disk *dsk) CAS_DEBUG_DISK(dsk, "Destroying (%p)", dsk); - list_del(&dsk->list); + close_bdev_exclusive(dsk->bd, CAS_DISK_OPEN_FMODE); - __cas_disk_close(dsk); + kfree(dsk->path); + kmem_cache_free(cas_module.disk_cache, dsk); } struct block_device *cas_disk_get_blkdev(struct cas_disk *dsk) @@ -213,15 +118,3 @@ struct request_queue *cas_disk_get_queue(struct cas_disk *dsk) BUG_ON(!dsk->bd); return cas_bdev_whole(dsk->bd)->bd_disk->queue; } - -int cas_disk_allocate_minors(int count) -{ - int minor = -1; - - if (cas_module.next_minor + count <= (1 << MINORBITS)) { - minor = cas_module.next_minor; - cas_module.next_minor += count; - } - - return minor; -} diff --git a/modules/cas_cache/disk.h b/modules/cas_cache/disk.h index a2bab73..7437673 100644 --- a/modules/cas_cache/disk.h +++ b/modules/cas_cache/disk.h @@ -5,7 +5,6 @@ #ifndef __CASDISK_DISK_H__ #define __CASDISK_DISK_H__ -#include #include #include #include @@ -15,48 +14,22 @@ struct cas_exp_obj; struct cas_disk { - uint32_t id; char *path; - struct mutex openers_lock; - unsigned int openers; - bool claimed; - struct block_device *bd; - int gd_flags; - int gd_minors; - - struct blk_mq_tag_set tag_set; struct cas_exp_obj *exp_obj; - - struct kobject kobj; - struct list_head list; - - void *private; }; int __init cas_init_disks(void); void cas_deinit_disks(void); -int cas_disk_allocate_minors(int count); - /** * @brief Open block device * @param path Path to block device - * @param private Private data * @return Pointer to cas_disk related to opened block device */ -struct cas_disk *cas_disk_open(const char *path, void *private); - -/** - * @brief Claim previously opened block device - * @param path Path to block device - * @param private Private data - * @return Pointer to cas_disk structure related to block device, or NULL - * if device is not opened. - */ -struct cas_disk *cas_disk_claim(const char *path, void *private); +struct cas_disk *cas_disk_open(const char *path); /** * @brief Close block device and remove from cas diff --git a/modules/cas_cache/exp_obj.c b/modules/cas_cache/exp_obj.c index 4d2895f..eff582b 100644 --- a/modules/cas_cache/exp_obj.c +++ b/modules/cas_cache/exp_obj.c @@ -19,11 +19,6 @@ #define CAS_DEV_MINORS 16 #define KMEM_CACHE_MIN_SIZE sizeof(void *) -static inline struct cas_exp_obj *cas_kobj_to_exp_obj(struct kobject *kobj) -{ - return container_of(kobj, struct cas_exp_obj, kobj); -} - static inline int bd_claim_by_disk(struct block_device *bdev, void *holder, struct gendisk *disk) { @@ -51,10 +46,20 @@ int __init cas_init_exp_objs(void) { CAS_DEBUG_TRACE(); + cas_module.disk_major = register_blkdev(cas_module.disk_major, + "cas"); + if (cas_module.disk_major <= 0) { + CAS_DEBUG_ERROR("Cannot allocate major number"); + return -EINVAL; + } + CAS_DEBUG_PARAM("Allocated major number: %d", cas_module.disk_major); + cas_module.exp_obj_cache = kmem_cache_create("cas_exp_obj", sizeof(struct cas_exp_obj), 0, 0, NULL); - if (!cas_module.exp_obj_cache) + if (!cas_module.exp_obj_cache) { + unregister_blkdev(cas_module.disk_major, "cas"); return -ENOMEM; + } return 0; } @@ -64,22 +69,19 @@ void cas_deinit_exp_objs(void) CAS_DEBUG_TRACE(); kmem_cache_destroy(cas_module.exp_obj_cache); -} - -static inline void _cas_exp_obj_handle_bio(struct cas_disk *dsk, - struct bio *bio) -{ - dsk->exp_obj->ops->submit_bio(dsk, bio, dsk->private); + unregister_blkdev(cas_module.disk_major, "cas"); } static MAKE_RQ_RET_TYPE _cas_exp_obj_submit_bio(struct bio *bio) { struct cas_disk *dsk; + struct cas_exp_obj *exp_obj; BUG_ON(!bio); dsk = CAS_BIO_GET_GENDISK(bio)->private_data; + exp_obj = dsk->exp_obj; - _cas_exp_obj_handle_bio(dsk, bio); + exp_obj->ops->submit_bio(dsk, bio, exp_obj->private); KRETURN(0); } @@ -167,6 +169,7 @@ static int _cas_flags = GENHD_FL_EXT_DEVT; static int _cas_exp_obj_hide_parts(struct cas_disk *dsk) { + struct cas_exp_obj *exp_obj = dsk->exp_obj; struct block_device *bd = cas_disk_get_blkdev(dsk); struct gendisk *gdsk = cas_disk_get_gendisk(dsk); @@ -186,8 +189,8 @@ static int _cas_exp_obj_hide_parts(struct cas_disk *dsk) } /* Save original flags and minors */ - dsk->gd_flags = gdsk->flags & _cas_flags; - dsk->gd_minors = gdsk->minors; + exp_obj->gd_flags = gdsk->flags & _cas_flags; + exp_obj->gd_minors = gdsk->minors; /* Setup disk of bottom device as not partitioned device */ gdsk->flags &= ~_cas_flags; @@ -198,8 +201,21 @@ static int _cas_exp_obj_hide_parts(struct cas_disk *dsk) return 0; } +static int _cas_exp_obj_allocate_minors(int count) +{ + int minor = -1; + + if (cas_module.next_minor + count <= (1 << MINORBITS)) { + minor = cas_module.next_minor; + cas_module.next_minor += count; + } + + return minor; +} + static int _cas_exp_obj_set_dev_t(struct cas_disk *dsk, struct gendisk *gd) { + struct cas_exp_obj *exp_obj = dsk->exp_obj; int flags; int minors = disk_max_parts(cas_disk_get_gendisk(dsk)); struct block_device *bdev; @@ -213,10 +229,10 @@ static int _cas_exp_obj_set_dev_t(struct cas_disk *dsk, struct gendisk *gd) } else { if (_cas_exp_obj_hide_parts(dsk)) return -EINVAL; - flags = dsk->gd_flags; + flags = exp_obj->gd_flags; } - gd->first_minor = cas_disk_allocate_minors(minors); + gd->first_minor = _cas_exp_obj_allocate_minors(minors); if (gd->first_minor < 0) { CAS_DEBUG_DISK_ERROR(dsk, "Cannot allocate %d minors", minors); return -EINVAL; @@ -231,13 +247,14 @@ static int _cas_exp_obj_set_dev_t(struct cas_disk *dsk, struct gendisk *gd) static void _cas_exp_obj_clear_dev_t(struct cas_disk *dsk) { + struct cas_exp_obj *exp_obj = dsk->exp_obj; struct block_device *bdev = cas_disk_get_blkdev(dsk); struct gendisk *gdsk = cas_disk_get_gendisk(dsk); if (cas_bdev_whole(bdev) == bdev) { /* Restore previous configuration of bottom disk */ - gdsk->minors = dsk->gd_minors; - gdsk->flags |= dsk->gd_flags; + gdsk->minors = exp_obj->gd_minors; + gdsk->flags |= exp_obj->gd_flags; cas_reread_partitions(bdev); } } @@ -245,32 +262,34 @@ static void _cas_exp_obj_clear_dev_t(struct cas_disk *dsk) static int _cas_exp_obj_open(struct block_device *bdev, fmode_t mode) { struct cas_disk *dsk = bdev->bd_disk->private_data; + struct cas_exp_obj *exp_obj = dsk->exp_obj; int result = -ENAVAIL; - mutex_lock(&dsk->openers_lock); + mutex_lock(&exp_obj->openers_lock); - if (!dsk->claimed) { - if (unlikely(dsk->openers == UINT_MAX)) { + if (!exp_obj->claimed) { + if (unlikely(exp_obj->openers == UINT_MAX)) { result = -EBUSY; } else { - dsk->openers++; + exp_obj->openers++; result = 0; } } - mutex_unlock(&dsk->openers_lock); + mutex_unlock(&dsk->exp_obj->openers_lock); return result; } static void _cas_exp_obj_close(struct gendisk *gd, fmode_t mode) { struct cas_disk *dsk = gd->private_data; + struct cas_exp_obj *exp_obj = dsk->exp_obj; - BUG_ON(dsk->openers == 0); + BUG_ON(exp_obj->openers == 0); - mutex_lock(&dsk->openers_lock); - dsk->openers--; - mutex_unlock(&dsk->openers_lock); + mutex_lock(&exp_obj->openers_lock); + exp_obj->openers--; + mutex_unlock(&exp_obj->openers_lock); } @@ -301,65 +320,15 @@ static int cas_exp_obj_alloc(struct cas_disk *dsk) return 0; } -void cas_exp_obj_free(struct cas_disk *dsk) +static void cas_exp_obj_free(struct cas_disk *dsk) { - struct cas_exp_obj *exp_obj; - - CAS_DEBUG_DISK_TRACE(dsk); - - exp_obj = dsk->exp_obj; - - if (!exp_obj) + if (!dsk->exp_obj) return; - kobject_put(&exp_obj->kobj); + kmem_cache_free(cas_module.exp_obj_cache, dsk->exp_obj); dsk->exp_obj = NULL; } -static void __cas_exp_obj_release(struct cas_exp_obj *exp_obj) -{ - kmem_cache_free(cas_module.exp_obj_cache, exp_obj); -} - -static void _cas_exp_obj_release(struct kobject *kobj) -{ - struct cas_exp_obj *exp_obj; - struct module *owner; - - BUG_ON(!kobj); - - exp_obj = cas_kobj_to_exp_obj(kobj); - BUG_ON(!exp_obj); - - CAS_DEBUG_TRACE(); - - owner = exp_obj->owner; - - kfree(exp_obj->dev_name); - __cas_exp_obj_release(exp_obj); - - if (owner) - module_put(owner); -} - -static struct kobj_type cas_exp_obj_ktype = { - .release = _cas_exp_obj_release -}; - -static int _cas_exp_obj_init_kobject(struct cas_disk *dsk) -{ - int result = 0; - struct cas_exp_obj *exp_obj = dsk->exp_obj; - - kobject_init(&exp_obj->kobj, &cas_exp_obj_ktype); - result = kobject_add(&exp_obj->kobj, &dsk->kobj, - "%s", exp_obj->dev_name); - if (result) - CAS_DEBUG_DISK_ERROR(dsk, "Cannot register kobject"); - - return result; -} - static CAS_BLK_STATUS_T _cas_exp_obj_queue_rq(struct blk_mq_hw_ctx *hctx, const struct blk_mq_queue_data *bd) { @@ -406,8 +375,38 @@ static int _cas_init_tag_set(struct cas_disk *dsk, struct blk_mq_tag_set *set) return blk_mq_alloc_tag_set(set); } +static int _cas_exp_obj_check_path(const char *dev_name) +{ + struct file *exported; + char *path; + int result; + + path = kmalloc(PATH_MAX, GFP_KERNEL); + if (!path) + return -ENOMEM; + + snprintf(path, PATH_MAX, "/dev/%s", dev_name); + + exported = filp_open(path, O_RDONLY, 0); + + if (!IS_ERR_OR_NULL(exported)) { + filp_close(exported, NULL); + result = -EEXIST; + + } else { + /* failed to open file - it is safe to assume, + * it does not exist + */ + result = 0; + } + + kfree(path); + + return result; +} + int cas_exp_obj_create(struct cas_disk *dsk, const char *dev_name, - struct module *owner, struct cas_exp_obj_ops *ops) + struct module *owner, struct cas_exp_obj_ops *ops, void *priv) { struct cas_exp_obj *exp_obj; struct request_queue *queue; @@ -424,12 +423,23 @@ int cas_exp_obj_create(struct cas_disk *dsk, const char *dev_name, if (strlen(dev_name) >= DISK_NAME_LEN) return -EINVAL; + result = _cas_exp_obj_check_path(dev_name); + if (result == -EEXIST) { + printk(KERN_ERR "Could not activate exported object, " + "because file /dev/%s exists.\n", dev_name); + } + + if (result) + return result; + result = cas_exp_obj_alloc(dsk); if (result) - goto error_exp_obj_alloc; + return result; exp_obj = dsk->exp_obj; + mutex_init(&exp_obj->openers_lock); + exp_obj->dev_name = kstrdup(dev_name, GFP_KERNEL); if (!exp_obj->dev_name) { result = -ENOMEM; @@ -444,17 +454,12 @@ int cas_exp_obj_create(struct cas_disk *dsk, const char *dev_name, exp_obj->owner = owner; exp_obj->ops = ops; - result = _cas_exp_obj_init_kobject(dsk); - if (result) { - goto error_init_kobject; - } - - result = _cas_init_tag_set(dsk, &dsk->tag_set); + result = _cas_init_tag_set(dsk, &exp_obj->tag_set); if (result) { goto error_init_tag_set; } - result = cas_alloc_mq_disk(&gd, &queue, &dsk->tag_set); + result = cas_alloc_mq_disk(&gd, &queue, &exp_obj->tag_set); if (result) { goto error_alloc_mq_disk; } @@ -469,6 +474,8 @@ int cas_exp_obj_create(struct cas_disk *dsk, const char *dev_name, queue->queuedata = dsk; exp_obj->queue = queue; + exp_obj->private = priv; + _cas_init_queues(dsk); gd->fops = &_cas_exp_obj_ops; @@ -478,159 +485,40 @@ int cas_exp_obj_create(struct cas_disk *dsk, const char *dev_name, cas_blk_queue_make_request(queue, _cas_exp_obj_make_rq_fn); if (exp_obj->ops->set_geometry) { - result = exp_obj->ops->set_geometry(dsk, dsk->private); + result = exp_obj->ops->set_geometry(dsk, exp_obj->private); if (result) goto error_set_geometry; } + add_disk(gd); + + result = bd_claim_by_disk(dsk->bd, dsk, gd); + if (result) + goto error_bd_claim; + return 0; +error_bd_claim: + del_gendisk(dsk->exp_obj->gd); error_set_geometry: + exp_obj->private = NULL; _cas_exp_obj_clear_dev_t(dsk); error_exp_obj_set_dev_t: cas_cleanup_mq_disk(exp_obj); dsk->exp_obj->gd = NULL; error_alloc_mq_disk: - blk_mq_free_tag_set(&dsk->tag_set); + blk_mq_free_tag_set(&exp_obj->tag_set); error_init_tag_set: - kobject_put(&exp_obj->kobj); - /* kobject put does all the cleanup below internally */ - return result; -error_init_kobject: module_put(owner); dsk->exp_obj->owner = NULL; error_module_get: kfree(exp_obj->dev_name); error_kstrdup: - __cas_exp_obj_release(exp_obj); - dsk->exp_obj = NULL; -error_exp_obj_alloc: + cas_exp_obj_free(dsk); return result; } -struct request_queue *cas_exp_obj_get_queue(struct cas_disk *dsk) -{ - BUG_ON(!dsk); - BUG_ON(!dsk->exp_obj); - return dsk->exp_obj->queue; -} - -struct gendisk *cas_exp_obj_get_gendisk(struct cas_disk *dsk) -{ - BUG_ON(!dsk); - BUG_ON(!dsk->exp_obj); - return dsk->exp_obj->gd; -} - -static bool _cas_exp_obj_exists(const char *path) -{ - struct file *exported; - - exported = filp_open(path, O_RDONLY, 0); - - if (!exported || IS_ERR(exported)) { - /*failed to open file - it is safe to assume, - * it does not exist - */ - return false; - } - - filp_close(exported, NULL); - return true; -} - -int cas_exp_obj_activate(struct cas_disk *dsk) -{ - char *path; - int result; - - BUG_ON(!dsk); - BUG_ON(!dsk->exp_obj); - BUG_ON(!dsk->exp_obj->gd); - BUG_ON(dsk->exp_obj->activated); - - CAS_DEBUG_DISK_TRACE(dsk); - - path = kmalloc(PATH_MAX, GFP_KERNEL); - if (!path) - return -ENOMEM; - - snprintf(path, PATH_MAX, "/dev/%s", dsk->exp_obj->dev_name); - if (_cas_exp_obj_exists(path)) { - printk(KERN_ERR "Could not activate exported object, " - "because file %s exists.\n", path); - kfree(path); - return -EEXIST; - } - kfree(path); - - dsk->exp_obj->activated = true; - add_disk(dsk->exp_obj->gd); - - result = bd_claim_by_disk(dsk->bd, dsk, dsk->exp_obj->gd); - if (result) - goto error_bd_claim; - - result = sysfs_create_link(&dsk->exp_obj->kobj, - &disk_to_dev(dsk->exp_obj->gd)->kobj, - "blockdev"); - if (result) - goto error_sysfs_link; - - CAS_DEBUG_DISK(dsk, "Activated exp object %s", dsk->exp_obj->dev_name); - - return 0; - -error_sysfs_link: - bd_release_from_disk(dsk->bd, dsk->exp_obj->gd); -error_bd_claim: - del_gendisk(dsk->exp_obj->gd); - dsk->exp_obj->activated = false; - return result; -} - -bool cas_exp_obj_activated(struct cas_disk *dsk) -{ - BUG_ON(!dsk); - return dsk->exp_obj->activated; -} - -int cas_exp_obj_lock(struct cas_disk *dsk) -{ - struct cas_exp_obj *exp_obj; - int result = -EBUSY; - - BUG_ON(!dsk); - BUG_ON(!dsk->exp_obj); - - CAS_DEBUG_DISK_TRACE(dsk); - - exp_obj = dsk->exp_obj; - - mutex_lock(&dsk->openers_lock); - - if (dsk->openers == 0) { - dsk->claimed = true; - result = 0; - } - - mutex_unlock(&dsk->openers_lock); - return result; -} - -int cas_exp_obj_unlock(struct cas_disk *dsk) -{ - BUG_ON(!dsk); - CAS_DEBUG_DISK_TRACE(dsk); - - mutex_lock(&dsk->openers_lock); - dsk->claimed = false; - mutex_unlock(&dsk->openers_lock); - - return 0; -} - int cas_exp_obj_destroy(struct cas_disk *dsk) { struct cas_exp_obj *exp_obj; @@ -644,20 +532,90 @@ int cas_exp_obj_destroy(struct cas_disk *dsk) exp_obj = dsk->exp_obj; - if (cas_exp_obj_activated(dsk)) { - sysfs_remove_link(&exp_obj->kobj, "blockdev"); - bd_release_from_disk(dsk->bd, exp_obj->gd); - _cas_exp_obj_clear_dev_t(dsk); - del_gendisk(exp_obj->gd); - } + bd_release_from_disk(dsk->bd, exp_obj->gd); + _cas_exp_obj_clear_dev_t(dsk); + del_gendisk(exp_obj->gd); if (exp_obj->queue) blk_cleanup_queue(exp_obj->queue); - blk_mq_free_tag_set(&dsk->tag_set); + blk_mq_free_tag_set(&exp_obj->tag_set); put_disk(exp_obj->gd); return 0; - +} + +void cas_exp_obj_cleanup(struct cas_disk *dsk) +{ + struct cas_exp_obj *exp_obj; + struct module *owner; + + CAS_DEBUG_DISK_TRACE(dsk); + + exp_obj = dsk->exp_obj; + + if (!exp_obj) + return; + + owner = exp_obj->owner; + + kfree(exp_obj->dev_name); + cas_exp_obj_free(dsk); + + if (owner) + module_put(owner); +} + +int cas_exp_obj_lock(struct cas_disk *dsk) +{ + struct cas_exp_obj *exp_obj; + int result = -EBUSY; + + BUG_ON(!dsk); + BUG_ON(!dsk->exp_obj); + + CAS_DEBUG_DISK_TRACE(dsk); + + exp_obj = dsk->exp_obj; + + mutex_lock(&exp_obj->openers_lock); + + if (exp_obj->openers == 0) { + exp_obj->claimed = true; + result = 0; + } + + mutex_unlock(&exp_obj->openers_lock); + return result; +} + +int cas_exp_obj_unlock(struct cas_disk *dsk) +{ + struct cas_exp_obj *exp_obj; + + BUG_ON(!dsk); + CAS_DEBUG_DISK_TRACE(dsk); + + exp_obj = dsk->exp_obj; + + mutex_lock(&exp_obj->openers_lock); + exp_obj->claimed = false; + mutex_unlock(&exp_obj->openers_lock); + + return 0; +} + +struct request_queue *cas_exp_obj_get_queue(struct cas_disk *dsk) +{ + BUG_ON(!dsk); + BUG_ON(!dsk->exp_obj); + return dsk->exp_obj->queue; +} + +struct gendisk *cas_exp_obj_get_gendisk(struct cas_disk *dsk) +{ + BUG_ON(!dsk); + BUG_ON(!dsk->exp_obj); + return dsk->exp_obj->gd; } diff --git a/modules/cas_cache/exp_obj.h b/modules/cas_cache/exp_obj.h index dfe4ecc..1c53657 100644 --- a/modules/cas_cache/exp_obj.h +++ b/modules/cas_cache/exp_obj.h @@ -5,7 +5,6 @@ #ifndef __CASDISK_EXP_OBJ_H__ #define __CASDISK_EXP_OBJ_H__ -#include #include struct cas_disk; @@ -34,21 +33,29 @@ struct cas_exp_obj { struct module *owner; - bool activated; - struct cas_exp_obj_ops *ops; const char *dev_name; - struct kobject kobj; + + struct mutex openers_lock; + unsigned int openers; + bool claimed; + + int gd_flags; + int gd_minors; + + struct blk_mq_tag_set tag_set; atomic_t pt_ios; atomic_t *pending_rqs; + + void *private; }; int __init cas_init_exp_objs(void); void cas_deinit_exp_objs(void); -void cas_exp_obj_free(struct cas_disk *dsk); +void cas_exp_obj_cleanup(struct cas_disk *dsk); /** * @brief Create exported object (top device) @@ -56,10 +63,11 @@ void cas_exp_obj_free(struct cas_disk *dsk); * @param dev_name Name of exported object (top device) * @param owner Pointer to cas module * @param ops Pointer to structure with callback functions + * @param priv Private data * @return 0 if success, errno if failure */ int cas_exp_obj_create(struct cas_disk *dsk, const char *dev_name, - struct module *owner, struct cas_exp_obj_ops *ops); + struct module *owner, struct cas_exp_obj_ops *ops, void *priv); /** * @brief Get request queue of exported object (top) block device @@ -75,14 +83,6 @@ struct request_queue *cas_exp_obj_get_queue(struct cas_disk *dsk); */ struct gendisk *cas_exp_obj_get_gendisk(struct cas_disk *dsk); -/** - * @brief Activate exported object (make it visible to OS - * and allow I/O handling) - * @param dsk Pointer to cas_disk structure representing a block device - * @return 0 if success, errno if failure - */ -int cas_exp_obj_activate(struct cas_disk *dsk); - /** * @brief Lock exported object * @param dsk Pointer to cas_disk structure representing a block device diff --git a/modules/cas_cache/layer_cache_management.c b/modules/cas_cache/layer_cache_management.c index c635d9b..4d8ccc3 100644 --- a/modules/cas_cache/layer_cache_management.c +++ b/modules/cas_cache/layer_cache_management.c @@ -1389,10 +1389,6 @@ int cache_mngt_add_core_to_cache(const char *cache_name, size_t name_len, if (result) goto error_after_add_core; - result = kcas_core_activate_exported_object(core); - if (result) - goto error_after_create_exported_object; - result = core_id_from_name(&core_id, cfg->name); if (result) goto error_after_create_exported_object; @@ -1768,8 +1764,6 @@ static int _cache_mngt_create_core_exp_obj(ocf_core_t core, void *cntx) if (result) return result; - result = kcas_core_activate_exported_object(core); - return result; } @@ -1830,12 +1824,6 @@ static int cache_mngt_initialize_cache_exported_object(ocf_cache_t cache) if (result) return result; - result = kcas_cache_activate_exported_object(cache); - if (result) { - cache_mngt_destroy_cache_exp_obj(cache); - return result; - } - cache_priv->cache_exp_obj_initialized = true; return 0; diff --git a/modules/cas_cache/volume/vol_block_dev_bottom.c b/modules/cas_cache/volume/vol_block_dev_bottom.c index f646815..5ecc07e 100644 --- a/modules/cas_cache/volume/vol_block_dev_bottom.c +++ b/modules/cas_cache/volume/vol_block_dev_bottom.c @@ -35,7 +35,7 @@ int block_dev_open_object(ocf_volume_t vol, void *volume_params) return 0; } - dsk = cas_disk_open(uuid->data, NULL); + dsk = cas_disk_open(uuid->data); if (IS_ERR_OR_NULL(dsk)) { int error = PTR_ERR(dsk) ?: -EINVAL; diff --git a/modules/cas_cache/volume/vol_block_dev_top.c b/modules/cas_cache/volume/vol_block_dev_top.c index c265742..bdefa3e 100644 --- a/modules/cas_cache/volume/vol_block_dev_top.c +++ b/modules/cas_cache/volume/vol_block_dev_top.c @@ -533,17 +533,9 @@ static int kcas_volume_create_exported_object(ocf_volume_t volume, const char *name, void *priv, struct cas_exp_obj_ops *ops) { struct bd_object *bvol = bd_object(volume); - const struct ocf_volume_uuid *uuid = ocf_volume_get_uuid(volume); char dev_name[DISK_NAME_LEN]; - struct cas_disk *dsk; int result; - dsk = cas_disk_claim(uuid->data, priv); - if (dsk != bvol->dsk) { - result = -KCAS_ERR_SYSTEM; - goto end; - } - bvol->expobj_wq = alloc_workqueue("expobj_wq_%s", WQ_MEM_RECLAIM | WQ_HIGHPRI, 0, name); @@ -552,8 +544,8 @@ static int kcas_volume_create_exported_object(ocf_volume_t volume, goto end; } - result = cas_exp_obj_create(dsk, name, - THIS_MODULE, ops); + result = cas_exp_obj_create(bvol->dsk, name, + THIS_MODULE, ops, priv); if (result) { destroy_workqueue(bvol->expobj_wq); goto end; @@ -590,12 +582,17 @@ static int kcas_volume_destroy_exported_object(ocf_volume_t volume) result = cas_exp_obj_destroy(bvol->dsk); if (result) - goto out; + goto err; bvol->expobj_valid = false; destroy_workqueue(bvol->expobj_wq); -out: + cas_exp_obj_unlock(bvol->dsk); + cas_exp_obj_cleanup(bvol->dsk); + + return 0; + +err: cas_exp_obj_unlock(bvol->dsk); return result; @@ -604,19 +601,6 @@ out: /** * @brief this routine actually adds /dev/casM-N inode */ -static int kcas_volume_activate_exported_object(ocf_volume_t volume, - struct cas_exp_obj_ops *ops) -{ - struct bd_object *bvol = bd_object(volume); - int result; - - result = cas_exp_obj_activate(bvol->dsk); - if (result == -EEXIST) - result = -KCAS_ERR_FILE_EXISTS; - - return result; -} - int kcas_core_create_exported_object(ocf_core_t core) { ocf_cache_t cache = ocf_core_get_cache(core); @@ -641,23 +625,6 @@ int kcas_core_destroy_exported_object(ocf_core_t core) return kcas_volume_destroy_exported_object(volume); } -int kcas_core_activate_exported_object(ocf_core_t core) -{ - ocf_cache_t cache = ocf_core_get_cache(core); - ocf_volume_t volume = ocf_core_get_volume(core); - int result; - - result = kcas_volume_activate_exported_object(volume, - &kcas_core_exp_obj_ops); - if (result) { - printk(KERN_ERR "Cannot activate exported object, %s.%s. " - "Error code %d\n", ocf_cache_get_name(cache), - ocf_core_get_name(core), result); - } - - return result; -} - int kcas_cache_create_exported_object(ocf_cache_t cache) { ocf_volume_t volume = ocf_cache_get_volume(cache); @@ -680,22 +647,6 @@ int kcas_cache_destroy_exported_object(ocf_cache_t cache) return kcas_volume_destroy_exported_object(volume); } -int kcas_cache_activate_exported_object(ocf_cache_t cache) -{ - ocf_volume_t volume = ocf_cache_get_volume(cache); - int result; - - result = kcas_volume_activate_exported_object(volume, - &kcas_cache_exp_obj_ops); - if (result) { - printk(KERN_ERR "Cannot activate cache %s exported object. " - "Error code %d\n", ocf_cache_get_name(cache), - result); - } - - return result; -} - static int kcas_core_lock_exported_object(ocf_core_t core, void *cntx) { int result; @@ -762,11 +713,11 @@ static int kcas_core_stop_exported_object(ocf_core_t core, void *cntx) return 0; } -static int kcas_core_free_exported_object(ocf_core_t core, void *cntx) +static int kcas_core_cleanup_exported_object(ocf_core_t core, void *cntx) { struct bd_object *bvol = bd_object(ocf_core_get_volume(core)); - cas_exp_obj_free(bvol->dsk); + cas_exp_obj_cleanup(bvol->dsk); return 0; } @@ -786,7 +737,7 @@ int kcas_cache_destroy_all_core_exported_objects(ocf_cache_t cache) } ocf_core_visit(cache, kcas_core_stop_exported_object, NULL, true); - ocf_core_visit(cache, kcas_core_free_exported_object, NULL, true); + ocf_core_visit(cache, kcas_core_cleanup_exported_object, NULL, true); return 0; } diff --git a/modules/cas_cache/volume/vol_block_dev_top.h b/modules/cas_cache/volume/vol_block_dev_top.h index 0c3320f..1ebc5a5 100644 --- a/modules/cas_cache/volume/vol_block_dev_top.h +++ b/modules/cas_cache/volume/vol_block_dev_top.h @@ -1,5 +1,5 @@ /* -* Copyright(c) 2012-2021 Intel Corporation +* Copyright(c) 2012-2022 Intel Corporation * SPDX-License-Identifier: BSD-3-Clause */ @@ -9,12 +9,10 @@ int kcas_core_create_exported_object(ocf_core_t core); int kcas_core_destroy_exported_object(ocf_core_t core); -int kcas_core_activate_exported_object(ocf_core_t core); int kcas_cache_destroy_all_core_exported_objects(ocf_cache_t cache); int kcas_cache_create_exported_object(ocf_cache_t cache); int kcas_cache_destroy_exported_object(ocf_cache_t cache); -int kcas_cache_activate_exported_object(ocf_cache_t cache); #endif /* __VOL_BLOCK_DEV_TOP_H__ */