aboutsummaryrefslogtreecommitdiffstats
path: root/tools/fs-back/fs-xenbus.c
blob: cc47dbcfd624e88b645da18d2bdf8fd9552bd0f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
#undef NDEBUG
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <assert.h>
#include <sys/select.h>
#include <xenctrl.h>
#include <xs.h>
#include <xen/io/fsif.h>
#include "fs-backend.h"
#include "fs-debug.h"


static bool xenbus_printf(struct xs_handle *xsh,
                          xs_transaction_t xbt,
                          char* node,
                          char* path,
                          char* fmt,
                          ...)
{
    char fullpath[1024];
    char val[1024];
    va_list args;
    
    va_start(args, fmt);
    snprintf(fullpath, sizeof(fullpath), "%s/%s", node, path);
    vsnprintf(val, sizeof(val), fmt, args);
    va_end(args);
    FS_DEBUG("xenbus_printf (%s) <= %s.\n", fullpath, val);    

    return xs_write(xsh, xbt, fullpath, val, strlen(val));
}

bool xenbus_create_request_node(void)
{
    bool ret;
    struct xs_permissions perms;
    
    assert(xsh != NULL);
    xs_rm(xsh, XBT_NULL, WATCH_NODE);
    ret = xs_mkdir(xsh, XBT_NULL, WATCH_NODE); 
    if (!ret)
        return false;

    perms.id = 0;
    perms.perms = XS_PERM_WRITE;
    ret = xs_set_permissions(xsh, XBT_NULL, WATCH_NODE, &perms, 1);

    return ret;
}

int xenbus_register_export(struct fs_export *export)
{
    xs_transaction_t xst = 0;
    char node[1024];
    struct xs_permissions perms;

    assert(xsh != NULL);
    if(xsh == NULL)
    {
        FS_DEBUG("Could not open connection to xenbus deamon.\n");
        goto error_exit;
    }
    FS_DEBUG("Connection to the xenbus deamon opened successfully.\n");

    /* Start transaction */
    xst = xs_transaction_start(xsh);
    if(xst == 0)
    {
        FS_DEBUG("Could not start a transaction.\n");
        goto error_exit;
    }
    FS_DEBUG("XS transaction is %d\n", xst); 
 
    /* Create node string */
    snprintf(node, sizeof(node), "%s/%d", EXPORTS_NODE, export->export_id); 
    /* Remove old export (if exists) */ 
    xs_rm(xsh, xst, node);

    if(!xenbus_printf(xsh, xst, node, "name", "%s", export->name))
    {
        FS_DEBUG("Could not write the export node.\n");
        goto error_exit;
    }

    /* People need to be able to read our export */
    perms.id = 0;
    perms.perms = XS_PERM_READ;
    if(!xs_set_permissions(xsh, xst, EXPORTS_NODE, &perms, 1))
    {
        FS_DEBUG("Could not set permissions on the export node.\n");
        goto error_exit;
    }

    xs_transaction_end(xsh, xst, 0);
    return 0; 

error_exit:    
    if(xst != 0)
        xs_transaction_end(xsh, xst, 1);
    return -1;
}

int xenbus_get_watch_fd(void)
{
    int res;
    assert(xsh != NULL);
    res = xs_watch(xsh, WATCH_NODE, "conn-watch");
    assert(res);
    return xs_fileno(xsh); 
}

void xenbus_read_mount_request(struct fs_mount *mount, char *frontend)
{
    char node[1024];
    char *s;
    int i;

    assert(xsh != NULL);
#if 0
    snprintf(node, sizeof(node), WATCH_NODE"/%d/%d/frontend", 
                           mount->dom_id, mount->export->export_id);
    frontend = xs_read(xsh, XBT_NULL, node, NULL);
#endif
    mount->frontend = frontend;
    snprintf(node, sizeof(node), "%s/state", frontend);
    s = xs_read(xsh, XBT_NULL, node, NULL);
    assert(strcmp(s, STATE_READY) == 0);
    free(s);
    snprintf(node, sizeof(node), "%s/ring-size", frontend);
    s = xs_read(xsh, XBT_NULL, node, NULL);
    mount->shared_ring_size = atoi(s);
    assert(mount->shared_ring_size <= MAX_RING_SIZE);
    free(s);
    for(i=0; i<mount->shared_ring_size; i++)
    {
        snprintf(node, sizeof(node), "%s/ring-ref-%d", frontend, i);
        s = xs_read(xsh, XBT_NULL, node, NULL);
        mount->grefs[i] = atoi(s);
        free(s);
    }
    snprintf(node, sizeof(node), "%s/event-channel", frontend);
    s = xs_read(xsh, XBT_NULL, node, NULL);
    mount->remote_evtchn = atoi(s);
    free(s);
}

/* Small utility function to figure out our domain id */
static int get_self_id(void)
{
    char *dom_id;
    int ret; 
                
    assert(xsh != NULL);
    dom_id = xs_read(xsh, XBT_NULL, "domid", NULL);
    sscanf(dom_id, "%d", &ret); 
    free(dom_id);
                        
    return ret;                                  
} 


void xenbus_write_backend_node(struct fs_mount *mount)
{
    char node[1024], backend_node[1024];
    int self_id;

    assert(xsh != NULL);
    self_id = get_self_id();
    FS_DEBUG("Our own dom_id=%d\n", self_id);
    snprintf(node, sizeof(node), "%s/backend", mount->frontend);
    snprintf(backend_node, sizeof(backend_node), "/local/domain/%d/"ROOT_NODE"/%d",
                                self_id, mount->mount_id);
    xs_write(xsh, XBT_NULL, node, backend_node, strlen(backend_node));

    snprintf(node, sizeof(node), ROOT_NODE"/%d/state", mount->mount_id);
    xs_write(xsh, XBT_NULL, node, STATE_INITIALISED, strlen(STATE_INITIALISED));
}

void xenbus_write_backend_state(struct fs_mount *mount, const char *state)
{
    char node[1024];
    int self_id;

    assert(xsh != NULL);
    self_id = get_self_id();
    snprintf(node, sizeof(node), ROOT_NODE"/%d/state", mount->mount_id);
    xs_write(xsh, XBT_NULL, node, state, strlen(state));
}

void xenbus_watch_frontend_state(struct fs_mount *mount)
{
    int res;
    char statepath[1024];

    assert(xsh != NULL);
    snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend);
    res = xs_watch(xsh, statepath, "frontend-state");
    assert(res);
}

void xenbus_unwatch_frontend_state(struct fs_mount *mount)
{
    int res;
    char statepath[1024];

    assert(xsh != NULL);
    snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend);
    res = xs_unwatch(xsh, statepath, "frontend-state");
    assert(res);
}

int xenbus_frontend_state_changed(struct fs_mount *mount, const char *oldstate)
{
    unsigned int len;
    char statepath[1024];
    char *state = NULL;

    assert(xsh != NULL);
    snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend);
    state = xs_read(xsh, XBT_NULL, statepath, &len);
    if (state && len > 0) {
        if (strcmp(state, oldstate)) {
            free(state);
            return 1;
        } else {
            free(state);
            return 0;
        }
    } else
        return 1;
}

char* xenbus_read_frontend_state(struct fs_mount *mount)
{
    unsigned int len;
    char statepath[1024];

    assert(xsh != NULL);
    snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend);
    return xs_read(xsh, XBT_NULL, statepath, &len);
}