Statistics
| Branch: | Tag: | Revision:

root / xseg / drivers / user / xseg_segdev.c @ 9fb0f83b

History | View | Annotate | Download (4.1 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
        XSEGLOG("creating segment of size %llu\n", size);
75

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

    
82
        return 0;
83
}
84

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

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

    
100
        closedev();
101
        return 0;
102
}
103

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

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

    
112
        fd = opendev();
113
        if (fd < 0)
114
                return NULL;
115

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

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

    
129
        return xseg;
130
}
131

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

    
138

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

    
151
static int segdev_local_signal_init(void)
152
{
153
        return -1;
154
}
155

    
156
static void segdev_local_signal_quit(void)
157
{
158
        return;
159
}
160

    
161
static int segdev_remote_signal_init(void)
162
{
163
        return 0;
164
}
165

    
166
static void segdev_remote_signal_quit(void)
167
{
168
        return;
169
}
170

    
171
static int segdev_prepare_wait(struct xseg *xseg, uint32_t portno)
172
{
173
        return -1;
174
}
175

    
176
static int segdev_cancel_wait(struct xseg *xseg, uint32_t portno)
177
{
178
        return -1;
179
}
180

    
181
static int segdev_wait_signal(struct xseg *xseg, uint32_t timeout)
182
{
183
        return -1;
184
}
185

    
186
static int segdev_signal(struct xseg *xseg, uint32_t portno)
187
{
188
        struct xseg_port *port = xseg_get_port(xseg, portno);
189
        if (!port)
190
                return -1;
191

    
192
        if (!port->waitcue)
193
                return 0;
194
        else
195
                return write(opendev(), &portno, sizeof(portno));
196
}
197

    
198
static void *segdev_malloc(uint64_t size)
199
{
200
        return NULL;
201
}
202

    
203
static void *segdev_realloc(void *mem, uint64_t size)
204
{
205
        return NULL;
206
}
207

    
208
static void segdev_mfree(void *mem) { }
209

    
210
static struct xseg_peer xseg_peer_segdev = {
211
        /* xseg signal operations */
212
        {
213
                .local_signal_init  = segdev_local_signal_init,
214
                .local_signal_quit  = segdev_local_signal_quit,
215
                .remote_signal_init = segdev_remote_signal_init,
216
                .remote_signal_quit = segdev_remote_signal_quit,
217
                .prepare_wait = segdev_prepare_wait,
218
                .cancel_wait = segdev_cancel_wait,
219
                .wait_signal = segdev_wait_signal,
220
                .signal = segdev_signal,
221
                .malloc = segdev_malloc,
222
                .realloc = segdev_realloc,
223
                .mfree = segdev_mfree
224
        },
225
        /* name */
226
        "segdev"
227
};
228

    
229
void xseg_segdev_init(void)
230
{
231
        xseg_register_type(&xseg_segdev);
232
        xseg_register_peer(&xseg_peer_segdev);
233
}
234