Statistics
| Branch: | Tag: | Revision:

root / xseg / drivers / user / xseg_segdev.c @ 7ce25cf6

History | View | Annotate | Download (3.7 kB)

1
#define _GNU_SOURCE
2
#include <stdio.h>
3
#include <stdlib.h>
4
#include <unistd.h>
5
#include <sys/types.h>
6
#include <sys/stat.h>
7
#include <sys/ioctl.h>
8
#include <sys/mman.h>
9
#include <sys/syscall.h>
10
#include <fcntl.h>
11
#include <errno.h>
12
#include <string.h>
13
#include <signal.h>
14
#include <xseg/xseg.h>
15
#include <sys/util.h>
16
#include <sys/kernel/segdev.h>
17

    
18
#define ERRSIZE 512
19
static char errbuf[ERRSIZE];
20

    
21
#define SEGDEV_DEVICE "/dev/segdev"
22
static int fdev = -1;
23

    
24
static int opendev(void)
25
{
26
        if (fdev >= 0)
27
                return fdev;
28

    
29
        fdev = open(SEGDEV_DEVICE, O_RDWR);
30
        if (fdev < 0) {
31
                XSEGLOG("Cannot open %s: %s\n", SEGDEV_DEVICE,
32
                        strerror_r(errno, errbuf, ERRSIZE));
33
                fdev = -1;
34
        }
35
        return fdev;
36
}
37

    
38
static int closedev(void)
39
{
40
        int r;
41
        if (fdev < 0)
42
                return 0;
43

    
44
        r = close(fdev);
45
        if (r < 0) {
46
                XSEGLOG("Cannot close %s: %s\n", SEGDEV_DEVICE,
47
                        strerror_r(errno, errbuf, ERRSIZE));
48
                return -1;
49
        } else
50
                fdev = -1;
51

    
52
        return 0;
53
}
54

    
55
static long segdev_allocate(const char *name, uint64_t size)
56
{
57
        int fd;
58
        long oldsize;
59

    
60
        fd = opendev();
61
        if (fd < 0)
62
                return fd;
63

    
64
        oldsize = ioctl(fd, SEGDEV_IOC_SEGSIZE, 0);
65
        if (oldsize >= 0) {
66
                XSEGLOG("Destroying old segment\n");
67
                if (ioctl(fd, SEGDEV_IOC_DESTROYSEG, 0)) {
68
                        XSEGLOG("Failed to destroy old segment");
69
                        closedev();
70
                        return -2;
71
                }
72
        }
73

    
74
        if (ioctl(fd, SEGDEV_IOC_CREATESEG, size)) {
75
                XSEGLOG("Failed to create segment");
76
                closedev();
77
                return -3;
78
        }
79

    
80
        return 0;
81
}
82

    
83
static long segdev_deallocate(const char *name)
84
{
85
        int fd;
86
        fd = open(SEGDEV_DEVICE, O_RDWR);
87
        if (fd < 0) {
88
                XSEGLOG("Cannot open %s: %s\n", SEGDEV_DEVICE,
89
                        strerror_r(errno, errbuf, ERRSIZE));
90
                return -1;
91
        }
92

    
93
        if (ioctl(fd, SEGDEV_IOC_DESTROYSEG, 0)) {
94
                XSEGLOG("Failed to destroy old segment");
95
                return -2;
96
        }
97

    
98
        closedev();
99
        return 0;
100
}
101

    
102
static void *segdev_map(const char *name, uint64_t size, struct xseg *seg)
103
{
104
        struct xseg *xseg;
105
        int fd;
106

    
107
        if (seg)
108
                XSEGLOG("struct xseg * not NULL. Ignoring...\n");
109

    
110
        fd = opendev();
111
        if (fd < 0)
112
                return NULL;
113

    
114
        xseg = mmap (        XSEG_BASE_AS_PTR,
115
                        size,
116
                        PROT_READ | PROT_WRITE,
117
                        MAP_SHARED | MAP_FIXED /* | MAP_LOCKED */,
118
                        fd, 0        );
119

    
120
        if (xseg == MAP_FAILED) {
121
                XSEGLOG("Could not map segment: %s\n",
122
                        strerror_r(errno, errbuf, ERRSIZE));
123
                closedev();
124
                return NULL;
125
        }
126

    
127
        return xseg;
128
}
129

    
130
static void segdev_unmap(void *ptr, uint64_t size)
131
{
132
        struct xseg *xseg = ptr;
133
        (void)munmap(xseg, xseg->segment_size);
134
}
135

    
136

    
137
static struct xseg_type xseg_segdev = {
138
        /* xseg_operations */
139
        {
140
                .allocate        = segdev_allocate,
141
                .deallocate        = segdev_deallocate,
142
                .map                = segdev_map,
143
                .unmap                = segdev_unmap
144
        },
145
        /* name */
146
        "segdev"
147
};
148

    
149
static int segdev_signal_init(void)
150
{
151
        return 0;
152
}
153

    
154
static void segdev_signal_quit(void)
155
{
156
        return;
157
}
158

    
159
static int segdev_prepare_wait(struct xseg *xseg, uint32_t portno)
160
{
161
        return -1;
162
}
163

    
164
static int segdev_cancel_wait(struct xseg *xseg, uint32_t portno)
165
{
166
        return -1;
167
}
168

    
169
static int segdev_wait_signal(struct xseg *xseg, uint32_t timeout)
170
{
171
        return -1;
172
}
173

    
174
static int segdev_signal(struct xseg *xseg, uint32_t portno)
175
{
176
        return write(opendev(), &portno, sizeof(portno));
177
}
178

    
179
static void *segdev_malloc(uint64_t size)
180
{
181
        return NULL;
182
}
183

    
184
static void *segdev_realloc(void *mem, uint64_t size)
185
{
186
        return NULL;
187
}
188

    
189
static void segdev_mfree(void *mem) { }
190

    
191
static struct xseg_peer xseg_peer_segdev = {
192
        /* xseg signal operations */
193
        {
194
                .signal_init = segdev_signal_init,
195
                .signal_quit = segdev_signal_quit,
196
                .prepare_wait = segdev_prepare_wait,
197
                .cancel_wait = segdev_cancel_wait,
198
                .wait_signal = segdev_wait_signal,
199
                .signal = segdev_signal,
200
                .malloc = segdev_malloc,
201
                .realloc = segdev_realloc,
202
                .mfree = segdev_mfree
203
        },
204
        /* name */
205
        "segdev"
206
};
207

    
208
void xseg_segdev_init(void)
209
{
210
        xseg_register_type(&xseg_segdev);
211
        xseg_register_peer(&xseg_peer_segdev);
212
}
213