📄 iscsi.c
字号:
hba->session_list_tail = NULL; } else if (session == hba->session_list_tail) { hba->session_list_tail = session->prev; hba->session_list_tail->next = NULL; } else { /* we should always be in the middle, * but check pointers to make sure we don't crash the kernel * if the function is called for a session not on the hba. */ if (session->next && session->prev) { session->next->prev = session->prev; session->prev->next = session->next; } else { DEBUG_ERR2("iSCSI: failed to remove session %p from hba %p\n", session, hba); return 0; } } session->prev = NULL; session->next = NULL; return 1;}static iscsi_session_t *find_session_for_cmnd(Scsi_Cmnd *sc) { iscsi_session_t *session = NULL; iscsi_hba_t *hba; DECLARE_NOQUEUE_FLAGS; if (!sc->host) return NULL; if (!sc->host->hostdata) return NULL; hba = (iscsi_hba_t *)sc->host->hostdata; /* find the session for this command */ SPIN_LOCK_NOQUEUE(&hba->session_lock); session = hba->session_list_head; while (session && (session->channel != sc->channel || session->target_id != sc->target)) session = session->next; if (session) atomic_inc(&session->refcount); /* caller must use drop_reference when it's done with the session */ SPIN_UNLOCK_NOQUEUE(&hba->session_lock); return session;}static iscsi_session_t *find_session_by_channel(unsigned int host_no, unsigned int channel, unsigned int target_id){ iscsi_session_t *session = NULL; iscsi_hba_t *hba; DECLARE_NOQUEUE_FLAGS; spin_lock(&iscsi_hba_list_lock); hba = iscsi_hba_list; while (hba && (hba->host_no != host_no)) { hba = hba->next; } /* find the session for this command */ if (hba) { SPIN_LOCK_NOQUEUE(&hba->session_lock); session = hba->session_list_head; while (session && (session->channel != channel || session->target_id != target_id)) session = session->next; if (session) atomic_inc(&session->refcount); /* caller must use drop_reference when it's done with the session */ SPIN_UNLOCK_NOQUEUE(&hba->session_lock); } spin_unlock(&iscsi_hba_list_lock); return session;}static iscsi_session_t *find_session_by_bus(int iscsi_bus, int target_id){ iscsi_session_t *session = NULL; iscsi_hba_t *hba; unsigned int hba_index; unsigned int channel; DECLARE_NOQUEUE_FLAGS; /* compute the appropriate HBA and channel numbers */ hba_index = iscsi_bus / ISCSI_MAX_CHANNELS_PER_HBA; channel = iscsi_bus % ISCSI_MAX_CHANNELS_PER_HBA; spin_lock(&iscsi_hba_list_lock); hba = iscsi_hba_list; while (hba && (hba_index-- > 0)) { hba = hba->next; } /* find the session for this command */ if (hba) { SPIN_LOCK_NOQUEUE(&hba->session_lock); session = hba->session_list_head; while (session && (session->channel != channel || session->target_id != target_id)) session = session->next; if (session) atomic_inc(&session->refcount); /* caller must use drop_reference when it's done with the session */ SPIN_UNLOCK_NOQUEUE(&hba->session_lock); } spin_unlock(&iscsi_hba_list_lock); return session;}static void delete_session(iscsi_session_t *session){ DEBUG_INIT1("iSCSI: terminated and deleted session %p\n", session); if (session->auth_client) { memset(session->auth_client, 0, sizeof(*session->auth_client)); kfree(session->auth_client); session->auth_client = NULL; } if (session->portals) { kfree(session->portals); session->portals = NULL; } memset(session, 0, sizeof(*session)); kfree(session);}/* decrement the session refcount, and remove it and free it if the refcount hit zero */static void drop_reference(iscsi_session_t *session){ iscsi_hba_t *hba; DECLARE_NOQUEUE_FLAGS; if (!session) { printk("iSCSI: bug - drop_reference(NULL)\n"); return; } if ((hba = session->hba)) { /* may need to remove it from the HBA's session list */ SPIN_LOCK_NOQUEUE(&hba->session_lock); if (atomic_dec_and_test(&session->refcount)) { if (remove_session(hba, session)) { delete_session(session); } else { printk("iSCSI: bug - failed to remove unreferenced session %p\n", session); } } SPIN_UNLOCK_NOQUEUE(&hba->session_lock); } else { /* session isn't in an HBA's list at the moment, so just check * the refcount, and possibly free it. */ if (atomic_dec_and_test(&session->refcount)) { delete_session(session); } }}/* must hold the task_lock to call this */static iscsi_task_t *find_task(iscsi_task_collection_t *collection, uint32_t itt){ iscsi_task_t *task = collection->head; while (task) { if (task->itt == itt) { DEBUG_FLOW3("iSCSI: found itt %u, task %p, refcount %d\n", itt, task, atomic_read(&task->refcount)); return task; } task = task->next; } return NULL;}/* don't actually use this at the moment *//* must hold the task_lock to call this */static iscsi_task_t *find_mgmt_task(iscsi_task_collection_t *collection, uint32_t mgmt_itt){ iscsi_task_t *task = collection->head; while (task) { if (task->mgmt_itt == mgmt_itt) { DEBUG_FLOW2("iSCSI: found mgmt_itt %u, task %p\n", mgmt_itt, task); return task; } task = task->next; } return NULL;}#if 0/* don't actually need this at the moment *//* must hold the task_lock to call this */static iscsi_task_t *find_task_for_cmnd(iscsi_task_collection_t *collection, Scsi_Cmnd *sc){ iscsi_task_t *task = collection->head; while (task) { if (task->scsi_cmnd == sc) { DEBUG_FLOW3("iSCSI: found itt %u, task %p for cmnd %p\n", task->itt, task, sc); return task; } task = task->next; } return NULL;}#endif/* add a task to the collection. Must hold the task_lock to do this. */static void add_task(iscsi_task_collection_t *collection, iscsi_task_t *task){ if (task->prev || task->next) printk("iSCSI: bug - adding task %p, prev %p, next %p, to collection %p\n", task, task->prev, task->next, collection); if (collection->head) { task->next = NULL; task->prev = collection->tail; collection->tail->next = task; collection->tail = task; } else { task->prev = task->next = NULL; collection->head = collection->tail = task; }}#define first_iscsi_task(collection_ptr) ((collection_ptr)->head)#define next_iscsi_task(collection_ptr, task_ptr) ((task_ptr)->next)#define order_next_task(collection_ptr, task_ptr) ((task_ptr)->order_next)/* must hold the task_lock when calling this */static iscsi_task_t *pop_task(iscsi_task_collection_t *collection){ iscsi_task_t *task = NULL; if ((task = collection->head)) { /* pop the head */ if ((collection->head = task->next)) collection->head->prev = NULL; else collection->tail = NULL; /* and return it */ task->prev = NULL; task->next = NULL; return task; } return NULL;}/* must hold the task_lock when calling this */static void push_task(iscsi_task_collection_t *collection, iscsi_task_t *task){ if (task) { task->prev = NULL; task->next = collection->head; if (collection->head) { collection->head->prev = task; collection->head = task; } else { collection->head = collection->tail = task; } }}static void unlink_task(iscsi_task_collection_t *collection, iscsi_task_t *task){ /* unlink the task from the collection */ if (task == collection->head) { if ((collection->head = task->next)) collection->head->prev = NULL; else collection->tail = NULL; } else if (task == collection->tail) { collection->tail = task->prev; collection->tail->next = NULL; } else { task->next->prev = task->prev; task->prev->next = task->next; } task->next = NULL; task->prev = NULL;}/* if the task for the itt is found in the collection, remove it, and return it. * otherwise, return NULL. Must hold the task_lock to call this. */static iscsi_task_t *remove_task(iscsi_task_collection_t *collection, uint32_t itt){ iscsi_task_t *task = NULL; iscsi_task_t *search = collection->head; while (search) { if (search->itt == itt) { task = search; unlink_task(collection, task); return task; } search = search->next; } return NULL;}/* if the task for the mgmt_itt is found in the collection, remove it, and return it. * otherwise, return NULL. Must hold the task_lock to call this. */static iscsi_task_t *remove_mgmt_task(iscsi_task_collection_t *collection, uint32_t mgmt_itt){ iscsi_task_t *task = NULL; iscsi_task_t *search = collection->head; while (search) { if (search->mgmt_itt == mgmt_itt) { task = search; unlink_task(collection, task); return task; } search = search->next; } return NULL;}/* if the task for the itt is found in the collection, remove it, and return it. * otherwise, return NULL. Must hold the task_lock to call this. */static iscsi_task_t *remove_task_for_cmnd(iscsi_task_collection_t *collection, Scsi_Cmnd *sc){ iscsi_task_t *task = NULL; iscsi_task_t *search = collection->head; while (search) { if (search->scsi_cmnd == sc) { task = search; unlink_task(collection, task); return task; } search = search->next; } return NULL;}/* * remove all tasks with the specified LUN. Must hold the task_lock to call this. */static void remove_tasks_for_lun(iscsi_task_collection_t *collection, int lun){ iscsi_task_t *search = collection->head; iscsi_task_t *next = NULL; while (search) { next = search->next; if (search->scsi_cmnd && search->scsi_cmnd->lun == lun) unlink_task(collection, search); search = next; }}/* must be called with no locks held, since it may sleep, and acquires * locks on it's own. */static iscsi_task_t *alloc_task(iscsi_session_t *session){ iscsi_task_t *task = NULL; iscsi_hba_t *hba = session->hba; if (!hba) { printk("iSCSI: alloc_task - session %p has NULL HBA\n", session); return NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -