Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/lib9p/lib9p.h
39475 views
1
/*
2
* Copyright 2016 Jakub Klama <[email protected]>
3
* All rights reserved
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted providing that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
*
14
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24
* POSSIBILITY OF SUCH DAMAGE.
25
*
26
*/
27
28
29
#ifndef LIB9P_LIB9P_H
30
#define LIB9P_LIB9P_H
31
32
#include <stdbool.h>
33
#include <stdio.h>
34
#include <sys/types.h>
35
#include <sys/queue.h>
36
#include <sys/uio.h>
37
#include <pthread.h>
38
39
#if defined(__FreeBSD__)
40
#include <sys/sbuf.h>
41
#else
42
#include "sbuf/sbuf.h"
43
#endif
44
45
#include "fcall.h"
46
#include "threadpool.h"
47
#include "hashtable.h"
48
49
#define L9P_DEFAULT_MSIZE 8192
50
#define L9P_MAX_IOV 128
51
#define L9P_NUMTHREADS 8
52
53
struct l9p_request;
54
struct l9p_backend;
55
struct l9p_fid;
56
57
/*
58
* Functions to implement underlying transport for lib9p.
59
*
60
* The transport is responsible for:
61
*
62
* - allocating a response buffer (filling in the iovec and niov)
63
* (gets req, pointer to base of iov array of size L9P_MAX_IOV,
64
* pointer to niov, lt_aux)
65
*
66
* - sending a response, when a request has a reply ready
67
* (gets req, pointer to iov, niov, actual response length, lt_aux)
68
*
69
* - dropping the response buffer, when a request has been
70
* flushed or otherwise dropped without a response
71
* (gets req, pointer to iov, niov, lt_aux)
72
*
73
* The transport is of course also responsible for feeding in
74
* request-buffers, but that happens by the transport calling
75
* l9p_connection_recv().
76
*/
77
struct l9p_transport {
78
void *lt_aux;
79
int (*lt_get_response_buffer)(struct l9p_request *, struct iovec *,
80
size_t *, void *);
81
int (*lt_send_response)(struct l9p_request *, const struct iovec *,
82
size_t, size_t, void *);
83
void (*lt_drop_response)(struct l9p_request *, const struct iovec *,
84
size_t, void *);
85
};
86
87
enum l9p_pack_mode {
88
L9P_PACK,
89
L9P_UNPACK
90
};
91
92
enum l9p_integer_type {
93
L9P_BYTE = 1,
94
L9P_WORD = 2,
95
L9P_DWORD = 4,
96
L9P_QWORD = 8
97
};
98
99
enum l9p_version {
100
L9P_INVALID_VERSION = 0,
101
L9P_2000 = 1,
102
L9P_2000U = 2,
103
L9P_2000L = 3
104
};
105
106
/*
107
* This structure is used for unpacking (decoding) incoming
108
* requests and packing (encoding) outgoing results. It has its
109
* own copy of the iov array, with its own counters for working
110
* through that array, but it borrows the actual DATA from the
111
* original iov array associated with the original request (see
112
* below).
113
*/
114
struct l9p_message {
115
enum l9p_pack_mode lm_mode;
116
struct iovec lm_iov[L9P_MAX_IOV];
117
size_t lm_niov;
118
size_t lm_cursor_iov;
119
size_t lm_cursor_offset;
120
size_t lm_size;
121
};
122
123
/*
124
* Data structure for a request/response pair (Tfoo/Rfoo).
125
*
126
* Note that the response is not formatted out into raw data
127
* (overwriting the request raw data) until we are really
128
* responding, with the exception of read operations Tread
129
* and Treaddir, which overlay their result-data into the
130
* iov array in the process of reading.
131
*
132
* We have room for two incoming fids, in case we are
133
* using 9P2000.L protocol. Note that nothing that uses two
134
* fids also has an output fid (newfid), so we could have a
135
* union of lr_fid2 and lr_newfid, but keeping them separate
136
* is probably a bit less error-prone. (If we want to shave
137
* memory requirements there are more places to look.)
138
*
139
* (The fid, fid2, and newfid fields should be removed via
140
* reorganization, as they are only used for smuggling data
141
* between request.c and the backend and should just be
142
* parameters to backend ops.)
143
*/
144
struct l9p_request {
145
struct l9p_message lr_req_msg; /* for unpacking the request */
146
struct l9p_message lr_resp_msg; /* for packing the response */
147
union l9p_fcall lr_req; /* the request, decoded/unpacked */
148
union l9p_fcall lr_resp; /* the response, not yet packed */
149
150
struct l9p_fid *lr_fid;
151
struct l9p_fid *lr_fid2;
152
struct l9p_fid *lr_newfid;
153
154
struct l9p_connection *lr_conn; /* containing connection */
155
void *lr_aux; /* reserved for transport layer */
156
157
struct iovec lr_data_iov[L9P_MAX_IOV]; /* iovecs for req + resp */
158
size_t lr_data_niov; /* actual size of data_iov */
159
160
int lr_error; /* result from l9p_dispatch_request */
161
162
/* proteced by threadpool mutex */
163
enum l9p_workstate lr_workstate; /* threadpool: work state */
164
enum l9p_flushstate lr_flushstate; /* flush state if flushee */
165
struct l9p_worker *lr_worker; /* threadpool: worker */
166
STAILQ_ENTRY(l9p_request) lr_worklink; /* reserved to threadpool */
167
168
/* protected by tag hash table lock */
169
struct l9p_request_queue lr_flushq; /* q of flushers */
170
STAILQ_ENTRY(l9p_request) lr_flushlink; /* link w/in flush queue */
171
};
172
173
/* N.B.: these dirents are variable length and for .L only */
174
struct l9p_dirent {
175
struct l9p_qid qid;
176
uint64_t offset;
177
uint8_t type;
178
char *name;
179
};
180
181
/*
182
* The 9pfs protocol has the notion of a "session", which is
183
* traffic between any two "Tversion" requests. All fids
184
* (lc_files, below) are specific to one particular session.
185
*
186
* We need a data structure per connection (client/server
187
* pair). This data structure lasts longer than these 9pfs
188
* sessions, but contains the request/response pairs and fids.
189
* Logically, the per-session data should be separate, but
190
* most of the time that would just require an extra
191
* indirection. Instead, a new session simply clunks all
192
* fids, and otherwise keeps using this same connection.
193
*/
194
struct l9p_connection {
195
struct l9p_server *lc_server;
196
struct l9p_transport lc_lt;
197
struct l9p_threadpool lc_tp;
198
enum l9p_version lc_version;
199
uint32_t lc_msize;
200
uint32_t lc_max_io_size;
201
struct ht lc_files;
202
struct ht lc_requests;
203
LIST_ENTRY(l9p_connection) lc_link;
204
};
205
206
struct l9p_server {
207
struct l9p_backend *ls_backend;
208
enum l9p_version ls_max_version;
209
LIST_HEAD(, l9p_connection) ls_conns;
210
};
211
212
int l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall,
213
enum l9p_version version);
214
ssize_t l9p_pustat(struct l9p_message *msg, struct l9p_stat *s,
215
enum l9p_version version);
216
uint16_t l9p_sizeof_stat(struct l9p_stat *stat, enum l9p_version version);
217
int l9p_pack_stat(struct l9p_message *msg, struct l9p_request *req,
218
struct l9p_stat *s);
219
ssize_t l9p_pudirent(struct l9p_message *msg, struct l9p_dirent *de);
220
221
int l9p_server_init(struct l9p_server **serverp, struct l9p_backend *backend);
222
223
int l9p_connection_init(struct l9p_server *server,
224
struct l9p_connection **connp);
225
void l9p_connection_free(struct l9p_connection *conn);
226
void l9p_connection_recv(struct l9p_connection *conn, const struct iovec *iov,
227
size_t niov, void *aux);
228
void l9p_connection_close(struct l9p_connection *conn);
229
struct l9p_fid *l9p_connection_alloc_fid(struct l9p_connection *conn,
230
uint32_t fid);
231
void l9p_connection_remove_fid(struct l9p_connection *conn,
232
struct l9p_fid *fid);
233
234
int l9p_dispatch_request(struct l9p_request *req);
235
void l9p_respond(struct l9p_request *req, bool drop, bool rmtag);
236
237
void l9p_init_msg(struct l9p_message *msg, struct l9p_request *req,
238
enum l9p_pack_mode mode);
239
void l9p_seek_iov(struct iovec *iov1, size_t niov1, struct iovec *iov2,
240
size_t *niov2, size_t seek);
241
size_t l9p_truncate_iov(struct iovec *iov, size_t niov, size_t length);
242
void l9p_describe_fcall(union l9p_fcall *fcall, enum l9p_version version,
243
struct sbuf *sb);
244
void l9p_freefcall(union l9p_fcall *fcall);
245
void l9p_freestat(struct l9p_stat *stat);
246
247
gid_t *l9p_getgrlist(const char *, gid_t, int *);
248
249
#endif /* LIB9P_LIB9P_H */
250
251