diff options
| -rw-r--r-- | drivers/lightnvm/core.c | 41 | ||||
| -rw-r--r-- | include/linux/lightnvm.h | 1 |
2 files changed, 32 insertions, 10 deletions
diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index e2abe88a139c..0e9f7996ff1d 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c | |||
| @@ -45,6 +45,8 @@ struct nvm_dev_map { | |||
| 45 | int num_ch; | 45 | int num_ch; |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | static void nvm_free(struct kref *ref); | ||
| 49 | |||
| 48 | static struct nvm_target *nvm_find_target(struct nvm_dev *dev, const char *name) | 50 | static struct nvm_target *nvm_find_target(struct nvm_dev *dev, const char *name) |
| 49 | { | 51 | { |
| 50 | struct nvm_target *tgt; | 52 | struct nvm_target *tgt; |
| @@ -501,6 +503,7 @@ static int nvm_remove_tgt(struct nvm_dev *dev, struct nvm_ioctl_remove *remove) | |||
| 501 | } | 503 | } |
| 502 | __nvm_remove_target(t, true); | 504 | __nvm_remove_target(t, true); |
| 503 | mutex_unlock(&dev->mlock); | 505 | mutex_unlock(&dev->mlock); |
| 506 | kref_put(&dev->ref, nvm_free); | ||
| 504 | 507 | ||
| 505 | return 0; | 508 | return 0; |
| 506 | } | 509 | } |
| @@ -1094,15 +1097,16 @@ err_fmtype: | |||
| 1094 | return ret; | 1097 | return ret; |
| 1095 | } | 1098 | } |
| 1096 | 1099 | ||
| 1097 | static void nvm_free(struct nvm_dev *dev) | 1100 | static void nvm_free(struct kref *ref) |
| 1098 | { | 1101 | { |
| 1099 | if (!dev) | 1102 | struct nvm_dev *dev = container_of(ref, struct nvm_dev, ref); |
| 1100 | return; | ||
| 1101 | 1103 | ||
| 1102 | if (dev->dma_pool) | 1104 | if (dev->dma_pool) |
| 1103 | dev->ops->destroy_dma_pool(dev->dma_pool); | 1105 | dev->ops->destroy_dma_pool(dev->dma_pool); |
| 1104 | 1106 | ||
| 1105 | nvm_unregister_map(dev); | 1107 | if (dev->rmap) |
| 1108 | nvm_unregister_map(dev); | ||
| 1109 | |||
| 1106 | kfree(dev->lun_map); | 1110 | kfree(dev->lun_map); |
| 1107 | kfree(dev); | 1111 | kfree(dev); |
| 1108 | } | 1112 | } |
| @@ -1139,7 +1143,13 @@ err: | |||
| 1139 | 1143 | ||
| 1140 | struct nvm_dev *nvm_alloc_dev(int node) | 1144 | struct nvm_dev *nvm_alloc_dev(int node) |
| 1141 | { | 1145 | { |
| 1142 | return kzalloc_node(sizeof(struct nvm_dev), GFP_KERNEL, node); | 1146 | struct nvm_dev *dev; |
| 1147 | |||
| 1148 | dev = kzalloc_node(sizeof(struct nvm_dev), GFP_KERNEL, node); | ||
| 1149 | if (dev) | ||
| 1150 | kref_init(&dev->ref); | ||
| 1151 | |||
| 1152 | return dev; | ||
| 1143 | } | 1153 | } |
| 1144 | EXPORT_SYMBOL(nvm_alloc_dev); | 1154 | EXPORT_SYMBOL(nvm_alloc_dev); |
| 1145 | 1155 | ||
| @@ -1147,12 +1157,16 @@ int nvm_register(struct nvm_dev *dev) | |||
| 1147 | { | 1157 | { |
| 1148 | int ret, exp_pool_size; | 1158 | int ret, exp_pool_size; |
| 1149 | 1159 | ||
| 1150 | if (!dev->q || !dev->ops) | 1160 | if (!dev->q || !dev->ops) { |
| 1161 | kref_put(&dev->ref, nvm_free); | ||
| 1151 | return -EINVAL; | 1162 | return -EINVAL; |
| 1163 | } | ||
| 1152 | 1164 | ||
| 1153 | ret = nvm_init(dev); | 1165 | ret = nvm_init(dev); |
| 1154 | if (ret) | 1166 | if (ret) { |
| 1167 | kref_put(&dev->ref, nvm_free); | ||
| 1155 | return ret; | 1168 | return ret; |
| 1169 | } | ||
| 1156 | 1170 | ||
| 1157 | exp_pool_size = max_t(int, PAGE_SIZE, | 1171 | exp_pool_size = max_t(int, PAGE_SIZE, |
| 1158 | (NVM_MAX_VLBA * (sizeof(u64) + dev->geo.sos))); | 1172 | (NVM_MAX_VLBA * (sizeof(u64) + dev->geo.sos))); |
| @@ -1162,7 +1176,7 @@ int nvm_register(struct nvm_dev *dev) | |||
| 1162 | exp_pool_size); | 1176 | exp_pool_size); |
| 1163 | if (!dev->dma_pool) { | 1177 | if (!dev->dma_pool) { |
| 1164 | pr_err("nvm: could not create dma pool\n"); | 1178 | pr_err("nvm: could not create dma pool\n"); |
| 1165 | nvm_free(dev); | 1179 | kref_put(&dev->ref, nvm_free); |
| 1166 | return -ENOMEM; | 1180 | return -ENOMEM; |
| 1167 | } | 1181 | } |
| 1168 | 1182 | ||
| @@ -1184,6 +1198,7 @@ void nvm_unregister(struct nvm_dev *dev) | |||
| 1184 | if (t->dev->parent != dev) | 1198 | if (t->dev->parent != dev) |
| 1185 | continue; | 1199 | continue; |
| 1186 | __nvm_remove_target(t, false); | 1200 | __nvm_remove_target(t, false); |
| 1201 | kref_put(&dev->ref, nvm_free); | ||
| 1187 | } | 1202 | } |
| 1188 | mutex_unlock(&dev->mlock); | 1203 | mutex_unlock(&dev->mlock); |
| 1189 | 1204 | ||
| @@ -1191,13 +1206,14 @@ void nvm_unregister(struct nvm_dev *dev) | |||
| 1191 | list_del(&dev->devices); | 1206 | list_del(&dev->devices); |
| 1192 | up_write(&nvm_lock); | 1207 | up_write(&nvm_lock); |
| 1193 | 1208 | ||
| 1194 | nvm_free(dev); | 1209 | kref_put(&dev->ref, nvm_free); |
| 1195 | } | 1210 | } |
| 1196 | EXPORT_SYMBOL(nvm_unregister); | 1211 | EXPORT_SYMBOL(nvm_unregister); |
| 1197 | 1212 | ||
| 1198 | static int __nvm_configure_create(struct nvm_ioctl_create *create) | 1213 | static int __nvm_configure_create(struct nvm_ioctl_create *create) |
| 1199 | { | 1214 | { |
| 1200 | struct nvm_dev *dev; | 1215 | struct nvm_dev *dev; |
| 1216 | int ret; | ||
| 1201 | 1217 | ||
| 1202 | down_write(&nvm_lock); | 1218 | down_write(&nvm_lock); |
| 1203 | dev = nvm_find_nvm_dev(create->dev); | 1219 | dev = nvm_find_nvm_dev(create->dev); |
| @@ -1208,7 +1224,12 @@ static int __nvm_configure_create(struct nvm_ioctl_create *create) | |||
| 1208 | return -EINVAL; | 1224 | return -EINVAL; |
| 1209 | } | 1225 | } |
| 1210 | 1226 | ||
| 1211 | return nvm_create_tgt(dev, create); | 1227 | kref_get(&dev->ref); |
| 1228 | ret = nvm_create_tgt(dev, create); | ||
| 1229 | if (ret) | ||
| 1230 | kref_put(&dev->ref, nvm_free); | ||
| 1231 | |||
| 1232 | return ret; | ||
| 1212 | } | 1233 | } |
| 1213 | 1234 | ||
| 1214 | static long nvm_ioctl_info(struct file *file, void __user *arg) | 1235 | static long nvm_ioctl_info(struct file *file, void __user *arg) |
diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index d3b02708e5f0..4d0d5655c7b2 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h | |||
| @@ -428,6 +428,7 @@ struct nvm_dev { | |||
| 428 | char name[DISK_NAME_LEN]; | 428 | char name[DISK_NAME_LEN]; |
| 429 | void *private_data; | 429 | void *private_data; |
| 430 | 430 | ||
| 431 | struct kref ref; | ||
| 431 | void *rmap; | 432 | void *rmap; |
| 432 | 433 | ||
| 433 | struct mutex mlock; | 434 | struct mutex mlock; |
