Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

scsi: lpfc: vmid: Introduce VMID in I/O path

Introduce the VMID in the I/O path. Check if the VMID is enabled and if
the I/O belongs to a VM or not.

Link: https://lore.kernel.org/r/20210608043556.274139-14-muneendra.kumar@broadcom.com
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Gaurav Srivastava <gaurav.srivastava@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Signed-off-by: Muneendra Kumar <muneendra.kumar@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Gaurav Srivastava and committed by
Martin K. Petersen
33c79741 0c4792c6

+174
+174
drivers/scsi/lpfc/lpfc_scsi.c
··· 5278 5278 } 5279 5279 } 5280 5280 5281 + /* 5282 + * lpfc_vmid_get_appid - get the VMID associated with the UUID 5283 + * @vport: The virtual port for which this call is being executed. 5284 + * @uuid: UUID associated with the VE 5285 + * @cmd: address of scsi_cmd descriptor 5286 + * @tag: VMID tag 5287 + * Returns status of the function 5288 + */ 5289 + static int lpfc_vmid_get_appid(struct lpfc_vport *vport, char *uuid, struct 5290 + scsi_cmnd * cmd, union lpfc_vmid_io_tag *tag) 5291 + { 5292 + struct lpfc_vmid *vmp = NULL; 5293 + int hash, len, rc, i; 5294 + 5295 + /* check if QFPA is complete */ 5296 + if (lpfc_vmid_is_type_priority_tag(vport) && !(vport->vmid_flag & 5297 + LPFC_VMID_QFPA_CMPL)) { 5298 + vport->work_port_events |= WORKER_CHECK_VMID_ISSUE_QFPA; 5299 + return -EAGAIN; 5300 + } 5301 + 5302 + /* search if the UUID has already been mapped to the VMID */ 5303 + len = strlen(uuid); 5304 + hash = lpfc_vmid_hash_fn(uuid, len); 5305 + 5306 + /* search for the VMID in the table */ 5307 + read_lock(&vport->vmid_lock); 5308 + vmp = lpfc_get_vmid_from_hashtable(vport, hash, uuid); 5309 + 5310 + /* if found, check if its already registered */ 5311 + if (vmp && vmp->flag & LPFC_VMID_REGISTERED) { 5312 + read_unlock(&vport->vmid_lock); 5313 + lpfc_vmid_update_entry(vport, cmd, vmp, tag); 5314 + rc = 0; 5315 + } else if (vmp && (vmp->flag & LPFC_VMID_REQ_REGISTER || 5316 + vmp->flag & LPFC_VMID_DE_REGISTER)) { 5317 + /* else if register or dereg request has already been sent */ 5318 + /* Hence VMID tag will not be added for this I/O */ 5319 + read_unlock(&vport->vmid_lock); 5320 + rc = -EBUSY; 5321 + } else { 5322 + /* The VMID was not found in the hashtable. At this point, */ 5323 + /* drop the read lock first before proceeding further */ 5324 + read_unlock(&vport->vmid_lock); 5325 + /* start the process to obtain one as per the */ 5326 + /* type of the VMID indicated */ 5327 + write_lock(&vport->vmid_lock); 5328 + vmp = lpfc_get_vmid_from_hashtable(vport, hash, uuid); 5329 + 5330 + /* while the read lock was released, in case the entry was */ 5331 + /* added by other context or is in process of being added */ 5332 + if (vmp && vmp->flag & LPFC_VMID_REGISTERED) { 5333 + lpfc_vmid_update_entry(vport, cmd, vmp, tag); 5334 + write_unlock(&vport->vmid_lock); 5335 + return 0; 5336 + } else if (vmp && vmp->flag & LPFC_VMID_REQ_REGISTER) { 5337 + write_unlock(&vport->vmid_lock); 5338 + return -EBUSY; 5339 + } 5340 + 5341 + /* else search and allocate a free slot in the hash table */ 5342 + if (vport->cur_vmid_cnt < vport->max_vmid) { 5343 + for (i = 0; i < vport->max_vmid; i++) { 5344 + vmp = vport->vmid + i; 5345 + if (vmp->flag == LPFC_VMID_SLOT_FREE) 5346 + break; 5347 + } 5348 + if (i == vport->max_vmid) 5349 + vmp = NULL; 5350 + } else { 5351 + vmp = NULL; 5352 + } 5353 + 5354 + if (!vmp) { 5355 + write_unlock(&vport->vmid_lock); 5356 + return -ENOMEM; 5357 + } 5358 + 5359 + /* Add the vmid and register */ 5360 + lpfc_put_vmid_in_hashtable(vport, hash, vmp); 5361 + vmp->vmid_len = len; 5362 + memcpy(vmp->host_vmid, uuid, vmp->vmid_len); 5363 + vmp->io_rd_cnt = 0; 5364 + vmp->io_wr_cnt = 0; 5365 + vmp->flag = LPFC_VMID_SLOT_USED; 5366 + 5367 + vmp->delete_inactive = 5368 + vport->vmid_inactivity_timeout ? 1 : 0; 5369 + 5370 + /* if type priority tag, get next available VMID */ 5371 + if (lpfc_vmid_is_type_priority_tag(vport)) 5372 + lpfc_vmid_assign_cs_ctl(vport, vmp); 5373 + 5374 + /* allocate the per cpu variable for holding */ 5375 + /* the last access time stamp only if VMID is enabled */ 5376 + if (!vmp->last_io_time) 5377 + vmp->last_io_time = __alloc_percpu(sizeof(u64), 5378 + __alignof__(struct 5379 + lpfc_vmid)); 5380 + if (!vmp->last_io_time) { 5381 + hash_del(&vmp->hnode); 5382 + vmp->flag = LPFC_VMID_SLOT_FREE; 5383 + write_unlock(&vport->vmid_lock); 5384 + return -EIO; 5385 + } 5386 + 5387 + write_unlock(&vport->vmid_lock); 5388 + 5389 + /* complete transaction with switch */ 5390 + if (lpfc_vmid_is_type_priority_tag(vport)) 5391 + rc = lpfc_vmid_uvem(vport, vmp, true); 5392 + else 5393 + rc = lpfc_vmid_cmd(vport, SLI_CTAS_RAPP_IDENT, vmp); 5394 + if (!rc) { 5395 + write_lock(&vport->vmid_lock); 5396 + vport->cur_vmid_cnt++; 5397 + vmp->flag |= LPFC_VMID_REQ_REGISTER; 5398 + write_unlock(&vport->vmid_lock); 5399 + } else { 5400 + write_lock(&vport->vmid_lock); 5401 + hash_del(&vmp->hnode); 5402 + vmp->flag = LPFC_VMID_SLOT_FREE; 5403 + free_percpu(vmp->last_io_time); 5404 + write_unlock(&vport->vmid_lock); 5405 + return -EIO; 5406 + } 5407 + 5408 + /* finally, enable the idle timer once */ 5409 + if (!(vport->phba->pport->vmid_flag & LPFC_VMID_TIMER_ENBLD)) { 5410 + mod_timer(&vport->phba->inactive_vmid_poll, 5411 + jiffies + 5412 + msecs_to_jiffies(1000 * LPFC_VMID_TIMER)); 5413 + vport->phba->pport->vmid_flag |= LPFC_VMID_TIMER_ENBLD; 5414 + } 5415 + } 5416 + return rc; 5417 + } 5418 + 5419 + /* 5420 + * lpfc_is_command_vm_io - get the UUID from blk cgroup 5421 + * @cmd: Pointer to scsi_cmnd data structure 5422 + * Returns UUID if present, otherwise NULL 5423 + */ 5424 + static char *lpfc_is_command_vm_io(struct scsi_cmnd *cmd) 5425 + { 5426 + char *uuid = NULL; 5427 + 5428 + if (cmd->request) { 5429 + if (cmd->request->bio) 5430 + uuid = blkcg_get_fc_appid(cmd->request->bio); 5431 + } 5432 + return uuid; 5433 + } 5434 + 5281 5435 /** 5282 5436 * lpfc_queuecommand - scsi_host_template queuecommand entry point 5283 5437 * @shost: kernel scsi host pointer. ··· 5457 5303 int err, idx; 5458 5304 #ifdef CONFIG_SCSI_LPFC_DEBUG_FS 5459 5305 uint64_t start = 0L; 5306 + u8 *uuid = NULL; 5460 5307 5461 5308 if (phba->ktime_on) 5462 5309 start = ktime_get_ns(); ··· 5585 5430 } 5586 5431 5587 5432 5433 + /* check the necessary and sufficient condition to support VMID */ 5434 + if (lpfc_is_vmid_enabled(phba) && 5435 + (ndlp->vmid_support || 5436 + phba->pport->vmid_priority_tagging == 5437 + LPFC_VMID_PRIO_TAG_ALL_TARGETS)) { 5438 + /* is the I/O generated by a VM, get the associated virtual */ 5439 + /* entity id */ 5440 + uuid = lpfc_is_command_vm_io(cmnd); 5441 + 5442 + if (uuid) { 5443 + err = lpfc_vmid_get_appid(vport, uuid, cmnd, 5444 + (union lpfc_vmid_io_tag *) 5445 + &lpfc_cmd->cur_iocbq.vmid_tag); 5446 + if (!err) 5447 + lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_VMID; 5448 + } 5449 + } 5450 + 5451 + atomic_inc(&ndlp->cmd_pending); 5588 5452 #ifdef CONFIG_SCSI_LPFC_DEBUG_FS 5589 5453 if (unlikely(phba->hdwqstat_on & LPFC_CHECK_SCSI_IO)) 5590 5454 this_cpu_inc(phba->sli4_hba.c_stat->xmt_io);