Skip to content

Commit a4131a5

Browse files
Naman Jainliuw
authored andcommitted
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: [email protected] Fixes: 0315fef ("uio_hv_generic: Align ring size to system page") Signed-off-by: Naman Jain <[email protected]> Reviewed-by: Saurabh Sengar <[email protected]> Reviewed-by: Long Li <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Wei Liu <[email protected]> Message-ID: <[email protected]>
1 parent 6f490bb commit a4131a5

File tree

1 file changed

+81
-10
lines changed

1 file changed

+81
-10
lines changed

tools/hv/hv_fcopy_uio_daemon.c

Lines changed: 81 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@
3535
#define WIN8_SRV_MINOR 1
3636
#define WIN8_SRV_VERSION (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR)
3737

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)
3942

4043
#define FCOPY_VER_COUNT 1
4144
static const int fcopy_versions[] = {
@@ -47,9 +50,62 @@ static const int fw_versions[] = {
4750
UTIL_FW_VERSION
4851
};
4952

50-
#define HV_RING_SIZE 0x4000 /* 16KB ring buffer size */
53+
static uint32_t get_ring_buffer_size(void)
54+
{
55+
char ring_path[PATH_MAX];
56+
DIR *dir;
57+
struct dirent *entry;
58+
struct stat st;
59+
uint32_t ring_size = 0;
60+
int retry_count = 0;
61+
62+
/* Find the channel directory */
63+
dir = opendir(FCOPY_CHANNELS_PATH);
64+
if (!dir) {
65+
usleep(100 * 1000); /* Avoid race with kernel, wait 100ms and retry once */
66+
dir = opendir(FCOPY_CHANNELS_PATH);
67+
if (!dir) {
68+
syslog(LOG_ERR, "Failed to open channels directory: %s", strerror(errno));
69+
return 0;
70+
}
71+
}
72+
73+
retry_once:
74+
while ((entry = readdir(dir)) != NULL) {
75+
if (entry->d_type == DT_DIR && strcmp(entry->d_name, ".") != 0 &&
76+
strcmp(entry->d_name, "..") != 0) {
77+
snprintf(ring_path, sizeof(ring_path), "%s/%s/ring",
78+
FCOPY_CHANNELS_PATH, entry->d_name);
79+
80+
if (stat(ring_path, &st) == 0) {
81+
/*
82+
* stat returns size of Tx, Rx rings combined,
83+
* so take half of it for individual ring size.
84+
*/
85+
ring_size = (uint32_t)st.st_size / 2;
86+
syslog(LOG_INFO, "Ring buffer size from %s: %u bytes",
87+
ring_path, ring_size);
88+
break;
89+
}
90+
}
91+
}
5192

52-
static unsigned char desc[HV_RING_SIZE];
93+
if (!ring_size && retry_count == 0) {
94+
retry_count = 1;
95+
rewinddir(dir);
96+
usleep(100 * 1000); /* Wait 100ms and retry once */
97+
goto retry_once;
98+
}
99+
100+
closedir(dir);
101+
102+
if (!ring_size)
103+
syslog(LOG_ERR, "Could not determine ring size");
104+
105+
return ring_size;
106+
}
107+
108+
static unsigned char *desc;
53109

54110
static int target_fd;
55111
static char target_fname[PATH_MAX];
@@ -397,7 +453,7 @@ int main(int argc, char *argv[])
397453
int daemonize = 1, long_index = 0, opt, ret = -EINVAL;
398454
struct vmbus_br txbr, rxbr;
399455
void *ring;
400-
uint32_t len = HV_RING_SIZE;
456+
uint32_t ring_size, len;
401457
char uio_name[NAME_MAX] = {0};
402458
char uio_dev_path[PATH_MAX] = {0};
403459

@@ -428,25 +484,38 @@ int main(int argc, char *argv[])
428484
openlog("HV_UIO_FCOPY", 0, LOG_USER);
429485
syslog(LOG_INFO, "starting; pid is:%d", getpid());
430486

431-
fcopy_get_first_folder(FCOPY_UIO, uio_name);
487+
ring_size = get_ring_buffer_size();
488+
if (!ring_size) {
489+
ret = -ENODEV;
490+
goto exit;
491+
}
492+
493+
desc = malloc(ring_size * sizeof(unsigned char));
494+
if (!desc) {
495+
syslog(LOG_ERR, "malloc failed for desc buffer");
496+
ret = -ENOMEM;
497+
goto exit;
498+
}
499+
500+
fcopy_get_first_folder(FCOPY_UIO_PATH, uio_name);
432501
snprintf(uio_dev_path, sizeof(uio_dev_path), "/dev/%s", uio_name);
433502
fcopy_fd = open(uio_dev_path, O_RDWR);
434503

435504
if (fcopy_fd < 0) {
436505
syslog(LOG_ERR, "open %s failed; error: %d %s",
437506
uio_dev_path, errno, strerror(errno));
438507
ret = fcopy_fd;
439-
goto exit;
508+
goto free_desc;
440509
}
441510

442-
ring = vmbus_uio_map(&fcopy_fd, HV_RING_SIZE);
511+
ring = vmbus_uio_map(&fcopy_fd, ring_size);
443512
if (!ring) {
444513
ret = errno;
445514
syslog(LOG_ERR, "mmap ringbuffer failed; error: %d %s", ret, strerror(ret));
446515
goto close;
447516
}
448-
vmbus_br_setup(&txbr, ring, HV_RING_SIZE);
449-
vmbus_br_setup(&rxbr, (char *)ring + HV_RING_SIZE, HV_RING_SIZE);
517+
vmbus_br_setup(&txbr, ring, ring_size);
518+
vmbus_br_setup(&rxbr, (char *)ring + ring_size, ring_size);
450519

451520
rxbr.vbr->imask = 0;
452521

@@ -463,7 +532,7 @@ int main(int argc, char *argv[])
463532
goto close;
464533
}
465534

466-
len = HV_RING_SIZE;
535+
len = ring_size;
467536
ret = rte_vmbus_chan_recv_raw(&rxbr, desc, &len);
468537
if (unlikely(ret <= 0)) {
469538
/* This indicates a failure to communicate (or worse) */
@@ -483,6 +552,8 @@ int main(int argc, char *argv[])
483552
}
484553
close:
485554
close(fcopy_fd);
555+
free_desc:
556+
free(desc);
486557
exit:
487558
return ret;
488559
}

0 commit comments

Comments
 (0)