aboutsummaryrefslogtreecommitdiffstats
path: root/tools/fs-back/fs-xenbus.c
blob: 6a86e245e0e28c00869688ba5ec90187f9af00d0 (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
#undef NDEBUG
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <assert.h>
#include <xenctrl.h>
#include <xs.h>
#include <xen/io/fsif.h>
#include "fs-backend.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);
    printf("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)
    {
        printf("Could not open connection to xenbus deamon.\n");
        goto error_exit;
    }
    printf("Connection to the xenbus deamon opened successfully.\n");

    /* Start transaction */
    xst = xs_transaction_start(xsh);
    if(xst == 0)
    {
        printf("Could not start a transaction.\n");
        goto error_exit;
    }
    printf("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))
    {
        printf("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))
    {
        printf("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();
    printf("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_ready(struct fs_mount *mount)
{
    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_READY, strlen(STATE_READY));
}