I have a driver which will dma_alloc a CMA region and return the address to
my user space program, the program then will mmap /dev/mem according to the
address offset. I was trying to vmsplice and splice it into my socket
buffer, but the vmsplice always return "bad address". Anybody knows why? I
attach my user space code for your perusal.
#define _GNU_SOURCE
#include <stdio.h>
// bind, socket, listen, accept
#include <sys/types.h>
#include <sys/socket.h>
//htons
#include <arpa/inet.h>
// exit
#include <stdlib.h>
// bzero
#include <strings.h>
// open
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
// mmap
#include <sys/mman.h>
// splice
#define _GNU_SOURCE
#include <fcntl.h>
// vmsplice
#define _GNU_SOURCE
#include <fcntl.h>
#include <sys/uio.h>
// pipe
#define _GNU_SOURCE
#include <fcntl.h>
#include <unistd.h>
#define BUFSIZE 0x1000
void error(const char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, ret, pagesize;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
int portno = 1234;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
error("Error opening socket\n");
bzero((char *)&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
int enable = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)
error("setsockopt(SO_REUSEADDR) failed");
if(bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
error("Error binding socket\n");
listen(sockfd, 5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
if(newsockfd < 0)
error("Error accept\n");
int memfd, pfd[2];
struct iovec iov;
void *buffer;
memfd = open("/dev/mem", O_RDWR | O_SYNC);
if (memfd < 0) {
perror("Cannot open /dev/mem\n");
exit(1);
}
pagesize = getpagesize();
buffer = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, memfd, 0xF100000);
if(buffer == MAP_FAILED)
error("mmap failed");
// This does not work
/* pipe(pfd);
iov.iov_base = buffer;
iov.iov_len = pagesize;
ret = vmsplice(pfd[1], &iov, 1, SPLICE_F_GIFT);
if(ret == -1)
error("vmsplice failed");
ret = splice(pfd[0], NULL, newsockfd, NULL, pagesize, SPLICE_F_MOVE);
if(ret == -1)
error("splice failed");*/
// This works
write(newsockfd, buffer, pagesize);
ret = munmap(buffer, pagesize);
if(ret == -1)
error("munmap failed");
close(memfd);
close(newsockfd);
close(sockfd);
return 0;
}_______________________________________________
Kernelnewbies mailing list
[email protected]
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies