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.

tools/hv: fcopy: Fix irregularities with size of ring buffer

Size of ring buffer, as defined in uio_hv_generic driver, is no longer
fixed to 16 KB. This creates a problem in fcopy, since this size was
hardcoded. With the change in place to make ring sysfs node actually
reflect the size of underlying ring buffer, it is safe to get the size
of ring sysfs file and use it for ring buffer size in fcopy daemon.
Fix the issue of disparity in ring buffer size, by making it dynamic
in fcopy uio daemon.

Cc: stable@vger.kernel.org
Fixes: 0315fef2aff9 ("uio_hv_generic: Align ring size to system page")
Signed-off-by: Naman Jain <namjain@linux.microsoft.com>
Reviewed-by: Saurabh Sengar <ssengar@linux.microsoft.com>
Reviewed-by: Long Li <longli@microsoft.com>
Link: https://lore.kernel.org/r/20250711060846.9168-1-namjain@linux.microsoft.com
Signed-off-by: Wei Liu <wei.liu@kernel.org>
Message-ID: <20250711060846.9168-1-namjain@linux.microsoft.com>

authored by

Naman Jain and committed by
Wei Liu
a4131a50 6f490bb4

+81 -10
+81 -10
tools/hv/hv_fcopy_uio_daemon.c
··· 35 35 #define WIN8_SRV_MINOR 1 36 36 #define WIN8_SRV_VERSION (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR) 37 37 38 - #define FCOPY_UIO "/sys/bus/vmbus/devices/eb765408-105f-49b6-b4aa-c123b64d17d4/uio" 38 + #define FCOPY_DEVICE_PATH(subdir) \ 39 + "/sys/bus/vmbus/devices/eb765408-105f-49b6-b4aa-c123b64d17d4/" #subdir 40 + #define FCOPY_UIO_PATH FCOPY_DEVICE_PATH(uio) 41 + #define FCOPY_CHANNELS_PATH FCOPY_DEVICE_PATH(channels) 39 42 40 43 #define FCOPY_VER_COUNT 1 41 44 static const int fcopy_versions[] = { ··· 50 47 UTIL_FW_VERSION 51 48 }; 52 49 53 - #define HV_RING_SIZE 0x4000 /* 16KB ring buffer size */ 50 + static uint32_t get_ring_buffer_size(void) 51 + { 52 + char ring_path[PATH_MAX]; 53 + DIR *dir; 54 + struct dirent *entry; 55 + struct stat st; 56 + uint32_t ring_size = 0; 57 + int retry_count = 0; 54 58 55 - static unsigned char desc[HV_RING_SIZE]; 59 + /* Find the channel directory */ 60 + dir = opendir(FCOPY_CHANNELS_PATH); 61 + if (!dir) { 62 + usleep(100 * 1000); /* Avoid race with kernel, wait 100ms and retry once */ 63 + dir = opendir(FCOPY_CHANNELS_PATH); 64 + if (!dir) { 65 + syslog(LOG_ERR, "Failed to open channels directory: %s", strerror(errno)); 66 + return 0; 67 + } 68 + } 69 + 70 + retry_once: 71 + while ((entry = readdir(dir)) != NULL) { 72 + if (entry->d_type == DT_DIR && strcmp(entry->d_name, ".") != 0 && 73 + strcmp(entry->d_name, "..") != 0) { 74 + snprintf(ring_path, sizeof(ring_path), "%s/%s/ring", 75 + FCOPY_CHANNELS_PATH, entry->d_name); 76 + 77 + if (stat(ring_path, &st) == 0) { 78 + /* 79 + * stat returns size of Tx, Rx rings combined, 80 + * so take half of it for individual ring size. 81 + */ 82 + ring_size = (uint32_t)st.st_size / 2; 83 + syslog(LOG_INFO, "Ring buffer size from %s: %u bytes", 84 + ring_path, ring_size); 85 + break; 86 + } 87 + } 88 + } 89 + 90 + if (!ring_size && retry_count == 0) { 91 + retry_count = 1; 92 + rewinddir(dir); 93 + usleep(100 * 1000); /* Wait 100ms and retry once */ 94 + goto retry_once; 95 + } 96 + 97 + closedir(dir); 98 + 99 + if (!ring_size) 100 + syslog(LOG_ERR, "Could not determine ring size"); 101 + 102 + return ring_size; 103 + } 104 + 105 + static unsigned char *desc; 56 106 57 107 static int target_fd; 58 108 static char target_fname[PATH_MAX]; ··· 453 397 int daemonize = 1, long_index = 0, opt, ret = -EINVAL; 454 398 struct vmbus_br txbr, rxbr; 455 399 void *ring; 456 - uint32_t len = HV_RING_SIZE; 400 + uint32_t ring_size, len; 457 401 char uio_name[NAME_MAX] = {0}; 458 402 char uio_dev_path[PATH_MAX] = {0}; 459 403 ··· 484 428 openlog("HV_UIO_FCOPY", 0, LOG_USER); 485 429 syslog(LOG_INFO, "starting; pid is:%d", getpid()); 486 430 487 - fcopy_get_first_folder(FCOPY_UIO, uio_name); 431 + ring_size = get_ring_buffer_size(); 432 + if (!ring_size) { 433 + ret = -ENODEV; 434 + goto exit; 435 + } 436 + 437 + desc = malloc(ring_size * sizeof(unsigned char)); 438 + if (!desc) { 439 + syslog(LOG_ERR, "malloc failed for desc buffer"); 440 + ret = -ENOMEM; 441 + goto exit; 442 + } 443 + 444 + fcopy_get_first_folder(FCOPY_UIO_PATH, uio_name); 488 445 snprintf(uio_dev_path, sizeof(uio_dev_path), "/dev/%s", uio_name); 489 446 fcopy_fd = open(uio_dev_path, O_RDWR); 490 447 ··· 505 436 syslog(LOG_ERR, "open %s failed; error: %d %s", 506 437 uio_dev_path, errno, strerror(errno)); 507 438 ret = fcopy_fd; 508 - goto exit; 439 + goto free_desc; 509 440 } 510 441 511 - ring = vmbus_uio_map(&fcopy_fd, HV_RING_SIZE); 442 + ring = vmbus_uio_map(&fcopy_fd, ring_size); 512 443 if (!ring) { 513 444 ret = errno; 514 445 syslog(LOG_ERR, "mmap ringbuffer failed; error: %d %s", ret, strerror(ret)); 515 446 goto close; 516 447 } 517 - vmbus_br_setup(&txbr, ring, HV_RING_SIZE); 518 - vmbus_br_setup(&rxbr, (char *)ring + HV_RING_SIZE, HV_RING_SIZE); 448 + vmbus_br_setup(&txbr, ring, ring_size); 449 + vmbus_br_setup(&rxbr, (char *)ring + ring_size, ring_size); 519 450 520 451 rxbr.vbr->imask = 0; 521 452 ··· 532 463 goto close; 533 464 } 534 465 535 - len = HV_RING_SIZE; 466 + len = ring_size; 536 467 ret = rte_vmbus_chan_recv_raw(&rxbr, desc, &len); 537 468 if (unlikely(ret <= 0)) { 538 469 /* This indicates a failure to communicate (or worse) */ ··· 552 483 } 553 484 close: 554 485 close(fcopy_fd); 486 + free_desc: 487 + free(desc); 555 488 exit: 556 489 return ret; 557 490 }