diff options
Diffstat (limited to 'drivers/scsi/scsi_transport_iscsi.c')
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 97 |
1 files changed, 68 insertions, 29 deletions
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index c0ec502835ee..f39da0cf5f18 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
@@ -287,20 +287,11 @@ void iscsi_block_session(struct iscsi_cls_session *session) | |||
287 | } | 287 | } |
288 | EXPORT_SYMBOL_GPL(iscsi_block_session); | 288 | EXPORT_SYMBOL_GPL(iscsi_block_session); |
289 | 289 | ||
290 | /** | ||
291 | * iscsi_create_session - create iscsi class session | ||
292 | * @shost: scsi host | ||
293 | * @transport: iscsi transport | ||
294 | * | ||
295 | * This can be called from a LLD or iscsi_transport. | ||
296 | **/ | ||
297 | struct iscsi_cls_session * | 290 | struct iscsi_cls_session * |
298 | iscsi_create_session(struct Scsi_Host *shost, | 291 | iscsi_alloc_session(struct Scsi_Host *shost, |
299 | struct iscsi_transport *transport) | 292 | struct iscsi_transport *transport) |
300 | { | 293 | { |
301 | struct iscsi_host *ihost; | ||
302 | struct iscsi_cls_session *session; | 294 | struct iscsi_cls_session *session; |
303 | int err; | ||
304 | 295 | ||
305 | session = kzalloc(sizeof(*session) + transport->sessiondata_size, | 296 | session = kzalloc(sizeof(*session) + transport->sessiondata_size, |
306 | GFP_KERNEL); | 297 | GFP_KERNEL); |
@@ -313,8 +304,20 @@ iscsi_create_session(struct Scsi_Host *shost, | |||
313 | INIT_LIST_HEAD(&session->host_list); | 304 | INIT_LIST_HEAD(&session->host_list); |
314 | INIT_LIST_HEAD(&session->sess_list); | 305 | INIT_LIST_HEAD(&session->sess_list); |
315 | 306 | ||
307 | session->dev.parent = &shost->shost_gendev; | ||
308 | session->dev.release = iscsi_session_release; | ||
309 | device_initialize(&session->dev); | ||
316 | if (transport->sessiondata_size) | 310 | if (transport->sessiondata_size) |
317 | session->dd_data = &session[1]; | 311 | session->dd_data = &session[1]; |
312 | return session; | ||
313 | } | ||
314 | EXPORT_SYMBOL_GPL(iscsi_alloc_session); | ||
315 | |||
316 | int iscsi_add_session(struct iscsi_cls_session *session) | ||
317 | { | ||
318 | struct Scsi_Host *shost = iscsi_session_to_shost(session); | ||
319 | struct iscsi_host *ihost; | ||
320 | int err; | ||
318 | 321 | ||
319 | /* this is released in the dev's release function */ | 322 | /* this is released in the dev's release function */ |
320 | scsi_host_get(shost); | 323 | scsi_host_get(shost); |
@@ -325,37 +328,51 @@ iscsi_create_session(struct Scsi_Host *shost, | |||
325 | 328 | ||
326 | snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", | 329 | snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", |
327 | session->sid); | 330 | session->sid); |
328 | session->dev.parent = &shost->shost_gendev; | 331 | err = device_add(&session->dev); |
329 | session->dev.release = iscsi_session_release; | ||
330 | err = device_register(&session->dev); | ||
331 | if (err) { | 332 | if (err) { |
332 | dev_printk(KERN_ERR, &session->dev, "iscsi: could not " | 333 | dev_printk(KERN_ERR, &session->dev, "iscsi: could not " |
333 | "register session's dev\n"); | 334 | "register session's dev\n"); |
334 | goto free_session; | 335 | goto release_host; |
335 | } | 336 | } |
336 | transport_register_device(&session->dev); | 337 | transport_register_device(&session->dev); |
337 | 338 | ||
338 | mutex_lock(&ihost->mutex); | 339 | mutex_lock(&ihost->mutex); |
339 | list_add(&session->host_list, &ihost->sessions); | 340 | list_add(&session->host_list, &ihost->sessions); |
340 | mutex_unlock(&ihost->mutex); | 341 | mutex_unlock(&ihost->mutex); |
342 | return 0; | ||
341 | 343 | ||
342 | return session; | 344 | release_host: |
343 | 345 | scsi_host_put(shost); | |
344 | free_session: | 346 | return err; |
345 | kfree(session); | ||
346 | return NULL; | ||
347 | } | 347 | } |
348 | 348 | EXPORT_SYMBOL_GPL(iscsi_add_session); | |
349 | EXPORT_SYMBOL_GPL(iscsi_create_session); | ||
350 | 349 | ||
351 | /** | 350 | /** |
352 | * iscsi_destroy_session - destroy iscsi session | 351 | * iscsi_create_session - create iscsi class session |
353 | * @session: iscsi_session | 352 | * @shost: scsi host |
353 | * @transport: iscsi transport | ||
354 | * | 354 | * |
355 | * Can be called by a LLD or iscsi_transport. There must not be | 355 | * This can be called from a LLD or iscsi_transport. |
356 | * any running connections. | ||
357 | **/ | 356 | **/ |
358 | int iscsi_destroy_session(struct iscsi_cls_session *session) | 357 | struct iscsi_cls_session * |
358 | iscsi_create_session(struct Scsi_Host *shost, | ||
359 | struct iscsi_transport *transport) | ||
360 | { | ||
361 | struct iscsi_cls_session *session; | ||
362 | |||
363 | session = iscsi_alloc_session(shost, transport); | ||
364 | if (!session) | ||
365 | return NULL; | ||
366 | |||
367 | if (iscsi_add_session(session)) { | ||
368 | iscsi_free_session(session); | ||
369 | return NULL; | ||
370 | } | ||
371 | return session; | ||
372 | } | ||
373 | EXPORT_SYMBOL_GPL(iscsi_create_session); | ||
374 | |||
375 | void iscsi_remove_session(struct iscsi_cls_session *session) | ||
359 | { | 376 | { |
360 | struct Scsi_Host *shost = iscsi_session_to_shost(session); | 377 | struct Scsi_Host *shost = iscsi_session_to_shost(session); |
361 | struct iscsi_host *ihost = shost->shost_data; | 378 | struct iscsi_host *ihost = shost->shost_data; |
@@ -367,11 +384,33 @@ int iscsi_destroy_session(struct iscsi_cls_session *session) | |||
367 | list_del(&session->host_list); | 384 | list_del(&session->host_list); |
368 | mutex_unlock(&ihost->mutex); | 385 | mutex_unlock(&ihost->mutex); |
369 | 386 | ||
387 | scsi_remove_target(&session->dev); | ||
388 | |||
370 | transport_unregister_device(&session->dev); | 389 | transport_unregister_device(&session->dev); |
371 | device_unregister(&session->dev); | 390 | device_del(&session->dev); |
372 | return 0; | ||
373 | } | 391 | } |
392 | EXPORT_SYMBOL_GPL(iscsi_remove_session); | ||
374 | 393 | ||
394 | void iscsi_free_session(struct iscsi_cls_session *session) | ||
395 | { | ||
396 | put_device(&session->dev); | ||
397 | } | ||
398 | |||
399 | EXPORT_SYMBOL_GPL(iscsi_free_session); | ||
400 | |||
401 | /** | ||
402 | * iscsi_destroy_session - destroy iscsi session | ||
403 | * @session: iscsi_session | ||
404 | * | ||
405 | * Can be called by a LLD or iscsi_transport. There must not be | ||
406 | * any running connections. | ||
407 | **/ | ||
408 | int iscsi_destroy_session(struct iscsi_cls_session *session) | ||
409 | { | ||
410 | iscsi_remove_session(session); | ||
411 | iscsi_free_session(session); | ||
412 | return 0; | ||
413 | } | ||
375 | EXPORT_SYMBOL_GPL(iscsi_destroy_session); | 414 | EXPORT_SYMBOL_GPL(iscsi_destroy_session); |
376 | 415 | ||
377 | static void iscsi_conn_release(struct device *dev) | 416 | static void iscsi_conn_release(struct device *dev) |