vmsplice returned "bad address"

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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
Kernelnewbies@xxxxxxxxxxxxxxxxx
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux