]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/scsi/scsi_transport_iscsi.c
Merge tag 'for-linus-5.6-ofs1' of git://git.kernel.org/pub/scm/linux/kernel/git/hubca...
[linux.git] / drivers / scsi / scsi_transport_iscsi.c
index ed8d9709b9b96ef4c70feb530bc346c50052bef6..dfc726fa34e34f5206101fdda0a84b2a9c3a7592 100644 (file)
@@ -2093,7 +2093,12 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
                                         "could not register session's dev\n");
                goto release_ida;
        }
-       transport_register_device(&session->dev);
+       err = transport_register_device(&session->dev);
+       if (err) {
+               iscsi_cls_session_printk(KERN_ERR, session,
+                                        "could not register transport's dev\n");
+               goto release_dev;
+       }
 
        spin_lock_irqsave(&sesslock, flags);
        list_add(&session->sess_list, &sesslist);
@@ -2103,6 +2108,8 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
        ISCSI_DBG_TRANS_SESSION(session, "Completed session adding\n");
        return 0;
 
+release_dev:
+       device_del(&session->dev);
 release_ida:
        if (session->ida_used)
                ida_simple_remove(&iscsi_sess_ida, session->target_id);
@@ -2263,7 +2270,12 @@ iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
                                         "register connection's dev\n");
                goto release_parent_ref;
        }
-       transport_register_device(&conn->dev);
+       err = transport_register_device(&conn->dev);
+       if (err) {
+               iscsi_cls_session_printk(KERN_ERR, session, "could not "
+                                        "register transport's dev\n");
+               goto release_conn_ref;
+       }
 
        spin_lock_irqsave(&connlock, flags);
        list_add(&conn->conn_list, &connlist);
@@ -2272,6 +2284,8 @@ iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
        ISCSI_DBG_TRANS_CONN(conn, "Completed conn creation\n");
        return conn;
 
+release_conn_ref:
+       put_device(&conn->dev);
 release_parent_ref:
        put_device(&session->dev);
 free_conn:
@@ -2947,6 +2961,24 @@ iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev)
        return err;
 }
 
+static int iscsi_session_has_conns(int sid)
+{
+       struct iscsi_cls_conn *conn;
+       unsigned long flags;
+       int found = 0;
+
+       spin_lock_irqsave(&connlock, flags);
+       list_for_each_entry(conn, &connlist, conn_list) {
+               if (iscsi_conn_get_sid(conn) == sid) {
+                       found = 1;
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&connlock, flags);
+
+       return found;
+}
+
 static int
 iscsi_set_iface_params(struct iscsi_transport *transport,
                       struct iscsi_uevent *ev, uint32_t len)
@@ -3524,10 +3556,12 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
                break;
        case ISCSI_UEVENT_DESTROY_SESSION:
                session = iscsi_session_lookup(ev->u.d_session.sid);
-               if (session)
-                       transport->destroy_session(session);
-               else
+               if (!session)
                        err = -EINVAL;
+               else if (iscsi_session_has_conns(ev->u.d_session.sid))
+                       err = -EBUSY;
+               else
+                       transport->destroy_session(session);
                break;
        case ISCSI_UEVENT_UNBIND_SESSION:
                session = iscsi_session_lookup(ev->u.d_session.sid);