📄 zfcp_aux.c
字号:
if (sg_list != NULL) { zfcp_sg_list_free(sg_list); kfree(sg_list); } kfree(sense_data); return retval;}/** * zfcp_sg_list_alloc - create a scatter-gather list of the specified size * @sg_list: structure describing a scatter gather list * @size: size of scatter-gather list * Return: 0 on success, else -ENOMEM * * In sg_list->sg a pointer to the created scatter-gather list is returned, * or NULL if we run out of memory. sg_list->count specifies the number of * elements of the scatter-gather list. The maximum size of a single element * in the scatter-gather list is PAGE_SIZE. */static inline intzfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size){ struct scatterlist *sg; unsigned int i; int retval = 0; void *address; BUG_ON(sg_list == NULL); sg_list->count = size >> PAGE_SHIFT; if (size & ~PAGE_MASK) sg_list->count++; sg_list->sg = kmalloc(sg_list->count * sizeof(struct scatterlist), GFP_KERNEL); if (sg_list->sg == NULL) { sg_list->count = 0; retval = -ENOMEM; goto out; } memset(sg_list->sg, 0, sg_list->count * sizeof(struct scatterlist)); for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) { sg->length = min(size, PAGE_SIZE); sg->offset = 0; address = (void *) get_zeroed_page(GFP_KERNEL); if (address == NULL) { sg_list->count = i; zfcp_sg_list_free(sg_list); retval = -ENOMEM; goto out; } zfcp_address_to_sg(address, sg); size -= sg->length; } out: return retval;}/** * zfcp_sg_list_free - free memory of a scatter-gather list * @sg_list: structure describing a scatter-gather list * * Memory for each element in the scatter-gather list is freed. * Finally sg_list->sg is freed itself and sg_list->count is reset. */static inline voidzfcp_sg_list_free(struct zfcp_sg_list *sg_list){ struct scatterlist *sg; unsigned int i; BUG_ON(sg_list == NULL); for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) free_page((unsigned long) zfcp_sg_to_address(sg)); sg_list->count = 0; kfree(sg_list->sg);}/** * zfcp_sg_size - determine size of a scatter-gather list * @sg: array of (struct scatterlist) * @sg_count: elements in array * Return: size of entire scatter-gather list */size_tzfcp_sg_size(struct scatterlist *sg, unsigned int sg_count){ unsigned int i; struct scatterlist *p; size_t size; size = 0; for (i = 0, p = sg; i < sg_count; i++, p++) { BUG_ON(p == NULL); size += p->length; } return size;}/** * zfcp_sg_list_copy_from_user -copy data from user space to scatter-gather list * @sg_list: structure describing a scatter-gather list * @user_buffer: pointer to buffer in user space * @size: number of bytes to be copied * Return: 0 on success, -EFAULT if copy_from_user fails. */static inline intzfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list, void __user *user_buffer, size_t size){ struct scatterlist *sg; unsigned int length; void *zfcp_buffer; int retval = 0; BUG_ON(sg_list == NULL); if (zfcp_sg_size(sg_list->sg, sg_list->count) < size) return -EFAULT; for (sg = sg_list->sg; size > 0; sg++) { length = min((unsigned int)size, sg->length); zfcp_buffer = zfcp_sg_to_address(sg); if (copy_from_user(zfcp_buffer, user_buffer, length)) { retval = -EFAULT; goto out; } user_buffer += length; size -= length; } out: return retval;}/** * zfcp_sg_list_copy_to_user - copy data from scatter-gather list to user space * @user_buffer: pointer to buffer in user space * @sg_list: structure describing a scatter-gather list * @size: number of bytes to be copied * Return: 0 on success, -EFAULT if copy_to_user fails */static inline intzfcp_sg_list_copy_to_user(void __user *user_buffer, struct zfcp_sg_list *sg_list, size_t size){ struct scatterlist *sg; unsigned int length; void *zfcp_buffer; int retval = 0; BUG_ON(sg_list == NULL); if (zfcp_sg_size(sg_list->sg, sg_list->count) < size) return -EFAULT; for (sg = sg_list->sg; size > 0; sg++) { length = min((unsigned int) size, sg->length); zfcp_buffer = zfcp_sg_to_address(sg); if (copy_to_user(user_buffer, zfcp_buffer, length)) { retval = -EFAULT; goto out; } user_buffer += length; size -= length; } out: return retval;}#undef ZFCP_LOG_AREA/****************************************************************//****** Functions for configuration/set-up of structures ********//****************************************************************/#define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG/** * zfcp_get_unit_by_lun - find unit in unit list of port by FCP LUN * @port: pointer to port to search for unit * @fcp_lun: FCP LUN to search for * Traverse list of all units of a port and return pointer to a unit * with the given FCP LUN. */struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, fcp_lun_t fcp_lun){ struct zfcp_unit *unit; int found = 0; list_for_each_entry(unit, &port->unit_list_head, list) { if ((unit->fcp_lun == fcp_lun) && !atomic_test_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status)) { found = 1; break; } } return found ? unit : NULL;}/** * zfcp_get_port_by_wwpn - find port in port list of adapter by wwpn * @adapter: pointer to adapter to search for port * @wwpn: wwpn to search for * Traverse list of all ports of an adapter and return pointer to a port * with the given wwpn. */struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, wwn_t wwpn){ struct zfcp_port *port; int found = 0; list_for_each_entry(port, &adapter->port_list_head, list) { if ((port->wwpn == wwpn) && !(atomic_read(&port->status) & (ZFCP_STATUS_PORT_NO_WWPN | ZFCP_STATUS_COMMON_REMOVE))) { found = 1; break; } } return found ? port : NULL;}/** * zfcp_get_port_by_did - find port in port list of adapter by d_id * @adapter: pointer to adapter to search for port * @d_id: d_id to search for * Traverse list of all ports of an adapter and return pointer to a port * with the given d_id. */struct zfcp_port *zfcp_get_port_by_did(struct zfcp_adapter *adapter, u32 d_id){ struct zfcp_port *port; int found = 0; list_for_each_entry(port, &adapter->port_list_head, list) { if ((port->d_id == d_id) && !atomic_test_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status)) { found = 1; break; } } return found ? port : NULL;}/** * zfcp_get_adapter_by_busid - find adpater in adapter list by bus_id * @bus_id: bus_id to search for * Traverse list of all adapters and return pointer to an adapter * with the given bus_id. */struct zfcp_adapter *zfcp_get_adapter_by_busid(char *bus_id){ struct zfcp_adapter *adapter; int found = 0; list_for_each_entry(adapter, &zfcp_data.adapter_list_head, list) { if ((strncmp(bus_id, zfcp_get_busid_by_adapter(adapter), BUS_ID_SIZE) == 0) && !atomic_test_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status)){ found = 1; break; } } return found ? adapter : NULL;}/** * zfcp_unit_enqueue - enqueue unit to unit list of a port. * @port: pointer to port where unit is added * @fcp_lun: FCP LUN of unit to be enqueued * Return: pointer to enqueued unit on success, NULL on error * Locks: config_sema must be held to serialize changes to the unit list * * Sets up some unit internal structures and creates sysfs entry. */struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun){ struct zfcp_unit *unit, *tmp_unit; scsi_lun_t scsi_lun; int found; /* * check that there is no unit with this FCP_LUN already in list * and enqueue it. * Note: Unlike for the adapter and the port, this is an error */ read_lock_irq(&zfcp_data.config_lock); unit = zfcp_get_unit_by_lun(port, fcp_lun); read_unlock_irq(&zfcp_data.config_lock); if (unit) return NULL; unit = kmalloc(sizeof (struct zfcp_unit), GFP_KERNEL); if (!unit) return NULL; memset(unit, 0, sizeof (struct zfcp_unit)); /* initialise reference count stuff */ atomic_set(&unit->refcount, 0); init_waitqueue_head(&unit->remove_wq); unit->port = port; unit->fcp_lun = fcp_lun; /* setup for sysfs registration */ snprintf(unit->sysfs_device.bus_id, BUS_ID_SIZE, "0x%016llx", fcp_lun); unit->sysfs_device.parent = &port->sysfs_device; unit->sysfs_device.release = zfcp_sysfs_unit_release; dev_set_drvdata(&unit->sysfs_device, unit); /* mark unit unusable as long as sysfs registration is not complete */ atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status); if (device_register(&unit->sysfs_device)) { kfree(unit); return NULL; } if (zfcp_sysfs_unit_create_files(&unit->sysfs_device)) { device_unregister(&unit->sysfs_device); return NULL; } zfcp_unit_get(unit); scsi_lun = 0; found = 0; write_lock_irq(&zfcp_data.config_lock); list_for_each_entry(tmp_unit, &port->unit_list_head, list) { if (tmp_unit->scsi_lun != scsi_lun) { found = 1; break; } scsi_lun++; } unit->scsi_lun = scsi_lun; if (found) list_add_tail(&unit->list, &tmp_unit->list); else list_add_tail(&unit->list, &port->unit_list_head); atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status); atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status); write_unlock_irq(&zfcp_data.config_lock); port->units++; zfcp_port_get(port); return unit;}voidzfcp_unit_dequeue(struct zfcp_unit *unit){ zfcp_unit_wait(unit); write_lock_irq(&zfcp_data.config_lock); list_del(&unit->list); write_unlock_irq(&zfcp_data.config_lock); unit->port->units--; zfcp_port_put(unit->port); zfcp_sysfs_unit_remove_files(&unit->sysfs_device); device_unregister(&unit->sysfs_device);}static void *zfcp_mempool_alloc(gfp_t gfp_mask, void *size){ return kmalloc((size_t) size, gfp_mask);}static voidzfcp_mempool_free(void *element, void *size){ kfree(element);}/* * Allocates a combined QTCB/fsf_req buffer for erp actions and fcp/SCSI * commands. * It also genrates fcp-nameserver request/response buffer and unsolicited * status read fsf_req buffers. * * locks: must only be called with zfcp_data.config_sema taken */static intzfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter){ adapter->pool.fsf_req_erp = mempool_create(ZFCP_POOL_FSF_REQ_ERP_NR, zfcp_mempool_alloc, zfcp_mempool_free, (void *) sizeof(struct zfcp_fsf_req_pool_element)); if (NULL == adapter->pool.fsf_req_erp) return -ENOMEM; adapter->pool.fsf_req_scsi = mempool_create(ZFCP_POOL_FSF_REQ_SCSI_NR, zfcp_mempool_alloc, zfcp_mempool_free, (void *) sizeof(struct zfcp_fsf_req_pool_element)); if (NULL == adapter->pool.fsf_req_scsi) return -ENOMEM; adapter->pool.fsf_req_abort = mempool_create(ZFCP_POOL_FSF_REQ_ABORT_NR, zfcp_mempool_alloc, zfcp_mempool_free, (void *) sizeof(struct zfcp_fsf_req_pool_element)); if (NULL == adapter->pool.fsf_req_abort) return -ENOMEM; adapter->pool.fsf_req_status_read = mempool_create(ZFCP_POOL_STATUS_READ_NR, zfcp_mempool_alloc, zfcp_mempool_free, (void *) sizeof(struct zfcp_fsf_req)); if (NULL == adapter->pool.fsf_req_status_read) return -ENOMEM; adapter->pool.data_status_read = mempool_create(ZFCP_POOL_STATUS_READ_NR, zfcp_mempool_alloc, zfcp_mempool_free, (void *) sizeof(struct fsf_status_read_buffer)); if (NULL == adapter->pool.data_status_read)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -