aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2006-06-28 13:00:30 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-06-29 11:08:46 -0400
commit8434aa8b6fe5af27a33b8aa830c24e3680356c83 (patch)
treedc8120fddd1d237dd9d47299b90c40874320daaf
parente6f3b63f50b4bb9fdc9025e0c3994acd265ad3a2 (diff)
[SCSI] iscsi: break up session creation into two stages
qla4xxx is initialized in two steps like other HW drivers. It allocates the host, sets up the HW, then adds the host. For iscsi part of HW setup is setting up persistent iscsi sessions. At that time, the interupts are off and the driver is not completely set up so we just want to allocate them. We do not want to add them to sysfs and expose them to userspace because userspace could try to do lots of fun things with them like scanning and at that time the driver is not ready. So this patch breakes up the session creation like other functions that use the driver model in two the alloc and add parts. When the driver is ready, it can then add the sessions and userspace can begin using them. This also fixes a bug in the addition error patch where we forgot to do a get on the session. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c97
-rw-r--r--include/scsi/scsi_transport_iscsi.h8
2 files changed, 76 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}
288EXPORT_SYMBOL_GPL(iscsi_block_session); 288EXPORT_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 **/
297struct iscsi_cls_session * 290struct iscsi_cls_session *
298iscsi_create_session(struct Scsi_Host *shost, 291iscsi_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}
314EXPORT_SYMBOL_GPL(iscsi_alloc_session);
315
316int 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; 344release_host:
343 345 scsi_host_put(shost);
344free_session: 346 return err;
345 kfree(session);
346 return NULL;
347} 347}
348 348EXPORT_SYMBOL_GPL(iscsi_add_session);
349EXPORT_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 **/
358int iscsi_destroy_session(struct iscsi_cls_session *session) 357struct iscsi_cls_session *
358iscsi_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}
373EXPORT_SYMBOL_GPL(iscsi_create_session);
374
375void 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}
392EXPORT_SYMBOL_GPL(iscsi_remove_session);
374 393
394void iscsi_free_session(struct iscsi_cls_session *session)
395{
396 put_device(&session->dev);
397}
398
399EXPORT_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 **/
408int iscsi_destroy_session(struct iscsi_cls_session *session)
409{
410 iscsi_remove_session(session);
411 iscsi_free_session(session);
412 return 0;
413}
375EXPORT_SYMBOL_GPL(iscsi_destroy_session); 414EXPORT_SYMBOL_GPL(iscsi_destroy_session);
376 415
377static void iscsi_conn_release(struct device *dev) 416static void iscsi_conn_release(struct device *dev)
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index 2e3cb37af047..53493d591355 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -199,6 +199,9 @@ struct iscsi_cls_session {
199#define iscsi_session_to_shost(_session) \ 199#define iscsi_session_to_shost(_session) \
200 dev_to_shost(_session->dev.parent) 200 dev_to_shost(_session->dev.parent)
201 201
202#define starget_to_session(_stgt) \
203 iscsi_dev_to_session(_stgt->dev.parent)
204
202struct iscsi_host { 205struct iscsi_host {
203 int next_target_id; 206 int next_target_id;
204 struct list_head sessions; 207 struct list_head sessions;
@@ -208,8 +211,13 @@ struct iscsi_host {
208/* 211/*
209 * session and connection functions that can be used by HW iSCSI LLDs 212 * session and connection functions that can be used by HW iSCSI LLDs
210 */ 213 */
214extern struct iscsi_cls_session *iscsi_alloc_session(struct Scsi_Host *shost,
215 struct iscsi_transport *transport);
216extern int iscsi_add_session(struct iscsi_cls_session *session);
211extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost, 217extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost,
212 struct iscsi_transport *t); 218 struct iscsi_transport *t);
219extern void iscsi_remove_session(struct iscsi_cls_session *session);
220extern void iscsi_free_session(struct iscsi_cls_session *session);
213extern int iscsi_destroy_session(struct iscsi_cls_session *session); 221extern int iscsi_destroy_session(struct iscsi_cls_session *session);
214extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess, 222extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess,
215 uint32_t cid); 223 uint32_t cid);