]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
31f18b77 | 4 | #include "include/compat.h" |
e306af50 | 5 | #include "include/ceph_fuse.h" |
7c673cae FG |
6 | #include "FuseStore.h" |
7 | #include "os/ObjectStore.h" | |
8 | #include "include/stringify.h" | |
9 | #include "common/errno.h" | |
10 | ||
1911f103 | 11 | #include <fuse_lowlevel.h> |
7c673cae FG |
12 | |
13 | #include <sys/types.h> | |
14 | #include <sys/stat.h> | |
15 | #include <unistd.h> | |
16 | #include <fcntl.h> /* Definition of AT_* constants */ | |
17 | #include <sys/stat.h> | |
18 | ||
11fdf7f2 | 19 | #if defined(__APPLE__) || defined(__FreeBSD__) |
7c673cae FG |
20 | #include <sys/param.h> |
21 | #include <sys/mount.h> | |
22 | #endif | |
23 | ||
24 | #define dout_context store->cct | |
25 | #define dout_subsys ceph_subsys_fuse | |
26 | #include "common/debug.h" | |
27 | #undef dout_prefix | |
28 | #define dout_prefix *_dout << "fuse " | |
29 | ||
30 | // some fuse-y bits of state | |
31 | struct fs_info { | |
32 | struct fuse_args args; | |
33 | struct fuse *f; | |
1911f103 | 34 | #if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0) |
7c673cae | 35 | struct fuse_chan *ch; |
1911f103 | 36 | #endif |
7c673cae FG |
37 | char *mountpoint; |
38 | }; | |
39 | ||
40 | int FuseStore::open_file(string p, struct fuse_file_info *fi, | |
41 | std::function<int(bufferlist *bl)> f) | |
42 | { | |
43 | if (open_files.count(p)) { | |
44 | OpenFile *o = open_files[p]; | |
45 | fi->fh = reinterpret_cast<uint64_t>(o); | |
46 | ++o->ref; | |
47 | return 0; | |
48 | } | |
49 | bufferlist bl; | |
50 | int r = f(&bl); | |
51 | if (r < 0) { | |
52 | return r; | |
53 | } | |
54 | OpenFile *o = new OpenFile; | |
55 | o->path = p; | |
56 | o->bl.claim(bl); | |
57 | open_files[p] = o; | |
58 | fi->fh = reinterpret_cast<uint64_t>(o); | |
59 | ++o->ref; | |
60 | return 0; | |
61 | } | |
62 | ||
63 | FuseStore::FuseStore(ObjectStore *s, string p) | |
64 | : store(s), | |
65 | mount_point(p), | |
66 | fuse_thread(this) | |
67 | { | |
68 | info = new fs_info(); | |
69 | } | |
70 | ||
71 | FuseStore::~FuseStore() | |
72 | { | |
73 | delete info; | |
74 | } | |
75 | ||
76 | /* | |
77 | * / - root directory | |
78 | * $cid/ | |
79 | * $cid/type - objectstore type | |
80 | * $cid/bitwise_hash_start = lowest hash value | |
81 | * $cid/bitwise_hash_end = highest hash value | |
82 | * $cid/bitwise_hash_bits - how many bits are significant | |
83 | * $cid/pgmeta/ - pgmeta object | |
84 | * $cid/all/ - all objects | |
85 | * $cid/all/$obj/ | |
86 | * $cid/all/$obj/bitwise_hash | |
87 | * $cid/all/$obj/data | |
88 | * $cid/all/$obj/omap/$key | |
89 | * $cid/all/$obj/attr/$name | |
90 | * $cid/by_bitwise_hash/$hash/$bits/$obj - all objects with this (bitwise) hash (prefix) | |
91 | */ | |
92 | enum { | |
93 | FN_ROOT = 1, | |
94 | FN_TYPE, | |
95 | FN_COLLECTION, | |
96 | FN_HASH_START, | |
97 | FN_HASH_END, | |
98 | FN_HASH_BITS, | |
99 | FN_OBJECT, | |
100 | FN_OBJECT_HASH, | |
101 | FN_OBJECT_DATA, | |
102 | FN_OBJECT_OMAP_HEADER, | |
103 | FN_OBJECT_OMAP, | |
104 | FN_OBJECT_OMAP_VAL, | |
105 | FN_OBJECT_ATTR, | |
106 | FN_OBJECT_ATTR_VAL, | |
107 | FN_ALL, | |
108 | FN_HASH_DIR, | |
109 | FN_HASH_VAL, | |
110 | }; | |
111 | ||
112 | static int parse_fn(CephContext* cct, const char *path, coll_t *cid, | |
113 | ghobject_t *oid, string *key, | |
114 | uint32_t *hash, uint32_t *hash_bits) | |
115 | { | |
116 | list<string> v; | |
117 | for (const char *p = path; *p; ++p) { | |
118 | if (*p == '/') | |
119 | continue; | |
120 | const char *e; | |
121 | for (e = p + 1; *e && *e != '/'; e++) ; | |
122 | string c(p, e-p); | |
123 | v.push_back(c); | |
124 | p = e; | |
125 | if (!*p) | |
126 | break; | |
127 | } | |
128 | ldout(cct, 10) << __func__ << " path " << path << " -> " << v << dendl; | |
129 | ||
130 | if (v.empty()) | |
131 | return FN_ROOT; | |
132 | ||
133 | if (v.front() == "type") | |
134 | return FN_TYPE; | |
135 | ||
136 | if (!cid->parse(v.front())) { | |
137 | return -ENOENT; | |
138 | } | |
139 | if (v.size() == 1) | |
140 | return FN_COLLECTION; | |
141 | v.pop_front(); | |
142 | ||
143 | if (v.front() == "bitwise_hash_start") | |
144 | return FN_HASH_START; | |
145 | if (v.front() == "bitwise_hash_end") | |
146 | return FN_HASH_END; | |
147 | if (v.front() == "bitwise_hash_bits") | |
148 | return FN_HASH_BITS; | |
149 | if (v.front() == "pgmeta") { | |
150 | spg_t pgid; | |
151 | if (cid->is_pg(&pgid)) { | |
152 | *oid = pgid.make_pgmeta_oid(); | |
153 | v.pop_front(); | |
154 | if (v.empty()) | |
155 | return FN_OBJECT; | |
156 | goto do_object; | |
157 | } | |
158 | return -ENOENT; | |
159 | } | |
160 | if (v.front() == "all") { | |
161 | v.pop_front(); | |
162 | if (v.empty()) | |
163 | return FN_ALL; | |
164 | goto do_dir; | |
165 | } | |
166 | if (v.front() == "by_bitwise_hash") { | |
167 | v.pop_front(); | |
168 | if (v.empty()) | |
169 | return FN_HASH_DIR; | |
170 | unsigned long hv, hm; | |
171 | int r = sscanf(v.front().c_str(), "%lx", &hv); | |
172 | if (r != 1) | |
173 | return -ENOENT; | |
174 | int shift = 32 - v.front().length() * 4; | |
175 | v.pop_front(); | |
176 | if (v.empty()) | |
177 | return FN_HASH_DIR; | |
178 | r = sscanf(v.front().c_str(), "%ld", &hm); | |
179 | if (r != 1) | |
180 | return -ENOENT; | |
181 | if (hm < 1 || hm > 32) | |
182 | return -ENOENT; | |
183 | v.pop_front(); | |
184 | *hash = hv << shift;//hobject_t::_reverse_bits(hv << shift); | |
185 | *hash_bits = hm; | |
186 | if (v.empty()) | |
187 | return FN_HASH_VAL; | |
188 | goto do_dir; | |
189 | } | |
190 | return -ENOENT; | |
191 | ||
192 | do_dir: | |
193 | { | |
194 | string o = v.front(); | |
195 | if (!oid->parse(o)) { | |
196 | return -ENOENT; | |
197 | } | |
198 | v.pop_front(); | |
199 | if (v.empty()) | |
200 | return FN_OBJECT; | |
201 | } | |
202 | ||
203 | do_object: | |
204 | if (v.front() == "data") | |
205 | return FN_OBJECT_DATA; | |
206 | if (v.front() == "omap_header") | |
207 | return FN_OBJECT_OMAP_HEADER; | |
208 | if (v.front() == "omap") { | |
209 | v.pop_front(); | |
210 | if (v.empty()) | |
211 | return FN_OBJECT_OMAP; | |
212 | *key = v.front(); | |
213 | v.pop_front(); | |
214 | if (v.empty()) | |
215 | return FN_OBJECT_OMAP_VAL; | |
216 | return -ENOENT; | |
217 | } | |
218 | if (v.front() == "attr") { | |
219 | v.pop_front(); | |
220 | if (v.empty()) | |
221 | return FN_OBJECT_ATTR; | |
222 | *key = v.front(); | |
223 | v.pop_front(); | |
224 | if (v.empty()) | |
225 | return FN_OBJECT_ATTR_VAL; | |
226 | return -ENOENT; | |
227 | } | |
228 | if (v.front() == "bitwise_hash") | |
229 | return FN_OBJECT_HASH; | |
230 | return -ENOENT; | |
231 | } | |
232 | ||
233 | ||
1911f103 TL |
234 | static int os_getattr(const char *path, struct stat *stbuf |
235 | #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0) | |
236 | , struct fuse_file_info *fi | |
237 | #endif | |
238 | ) | |
7c673cae FG |
239 | { |
240 | fuse_context *fc = fuse_get_context(); | |
241 | FuseStore *fs = static_cast<FuseStore*>(fc->private_data); | |
242 | ldout(fs->store->cct, 10) << __func__ << " " << path << dendl; | |
243 | coll_t cid; | |
244 | ghobject_t oid; | |
245 | string key; | |
246 | uint32_t hash_value, hash_bits; | |
247 | int t = parse_fn(fs->store->cct, path, &cid, &oid, &key, &hash_value, | |
248 | &hash_bits); | |
249 | if (t < 0) | |
250 | return t; | |
251 | ||
252 | std::lock_guard<std::mutex> l(fs->lock); | |
253 | ||
254 | stbuf->st_size = 0; | |
255 | stbuf->st_uid = 0; | |
256 | stbuf->st_gid = 0; | |
257 | stbuf->st_mode = S_IFREG | 0700; | |
258 | ||
11fdf7f2 TL |
259 | auto ch = fs->store->open_collection(cid); |
260 | ||
7c673cae FG |
261 | switch (t) { |
262 | case FN_OBJECT_OMAP: | |
263 | case FN_OBJECT_ATTR: | |
264 | case FN_OBJECT: | |
265 | case FN_OBJECT_DATA: | |
266 | case FN_OBJECT_OMAP_HEADER: | |
267 | case FN_OBJECT_OMAP_VAL: | |
268 | { | |
269 | spg_t pgid; | |
270 | if (cid.is_pg(&pgid)) { | |
11fdf7f2 TL |
271 | if (!ch) { |
272 | return -ENOENT; | |
273 | } | |
274 | int bits = fs->store->collection_bits(ch); | |
7c673cae FG |
275 | if (bits >= 0 && !oid.match(bits, pgid.ps())) { |
276 | // sorry, not part of this PG | |
277 | return -ENOENT; | |
278 | } | |
279 | } | |
280 | } | |
281 | break; | |
282 | } | |
283 | ||
284 | switch (t) { | |
285 | case FN_OBJECT_OMAP: | |
286 | case FN_OBJECT_ATTR: | |
287 | case FN_OBJECT: | |
11fdf7f2 | 288 | if (!fs->store->exists(ch, oid)) |
7c673cae FG |
289 | return -ENOENT; |
290 | // fall-thru | |
291 | case FN_ALL: | |
292 | case FN_HASH_DIR: | |
293 | case FN_HASH_VAL: | |
294 | case FN_COLLECTION: | |
295 | if (!fs->store->collection_exists(cid)) | |
296 | return -ENOENT; | |
297 | // fall-thru | |
298 | case FN_ROOT: | |
299 | stbuf->st_mode = S_IFDIR | 0700; | |
300 | return 0; | |
301 | ||
302 | case FN_TYPE: | |
303 | stbuf->st_size = fs->store->get_type().length() + 1; | |
304 | break; | |
305 | ||
306 | case FN_OBJECT_HASH: | |
11fdf7f2 | 307 | if (!fs->store->exists(ch, oid)) |
7c673cae FG |
308 | return -ENOENT; |
309 | stbuf->st_size = 9; | |
310 | return 0; | |
311 | ||
312 | case FN_HASH_END: | |
11fdf7f2 | 313 | if (!ch) |
7c673cae | 314 | return -ENOENT; |
11fdf7f2 | 315 | if (fs->store->collection_bits(ch) < 0) |
7c673cae FG |
316 | return -ENOENT; |
317 | // fall-thru | |
318 | case FN_HASH_START: | |
319 | stbuf->st_size = 9; | |
320 | return 0; | |
321 | ||
322 | case FN_HASH_BITS: | |
323 | { | |
11fdf7f2 | 324 | if (!ch) |
7c673cae | 325 | return -ENOENT; |
11fdf7f2 | 326 | int bits = fs->store->collection_bits(ch); |
7c673cae FG |
327 | if (bits < 0) |
328 | return -ENOENT; | |
11fdf7f2 | 329 | char buf[12]; |
7c673cae FG |
330 | snprintf(buf, sizeof(buf), "%d\n", bits); |
331 | stbuf->st_size = strlen(buf); | |
332 | } | |
333 | return 0; | |
334 | ||
335 | case FN_OBJECT_DATA: | |
336 | { | |
11fdf7f2 | 337 | if (!fs->store->exists(ch, oid)) |
7c673cae | 338 | return -ENOENT; |
11fdf7f2 | 339 | int r = fs->store->stat(ch, oid, stbuf); |
7c673cae FG |
340 | if (r < 0) |
341 | return r; | |
342 | } | |
343 | break; | |
344 | ||
345 | case FN_OBJECT_OMAP_HEADER: | |
346 | { | |
11fdf7f2 | 347 | if (!fs->store->exists(ch, oid)) |
7c673cae FG |
348 | return -ENOENT; |
349 | bufferlist bl; | |
11fdf7f2 | 350 | fs->store->omap_get_header(ch, oid, &bl); |
7c673cae FG |
351 | stbuf->st_size = bl.length(); |
352 | } | |
353 | break; | |
354 | ||
355 | case FN_OBJECT_OMAP_VAL: | |
356 | { | |
11fdf7f2 | 357 | if (!fs->store->exists(ch, oid)) |
7c673cae FG |
358 | return -ENOENT; |
359 | set<string> k; | |
360 | k.insert(key); | |
361 | map<string,bufferlist> v; | |
11fdf7f2 | 362 | fs->store->omap_get_values(ch, oid, k, &v); |
7c673cae FG |
363 | if (!v.count(key)) { |
364 | return -ENOENT; | |
365 | } | |
366 | stbuf->st_size = v[key].length(); | |
367 | } | |
368 | break; | |
369 | ||
370 | case FN_OBJECT_ATTR_VAL: | |
371 | { | |
11fdf7f2 | 372 | if (!fs->store->exists(ch, oid)) |
7c673cae FG |
373 | return -ENOENT; |
374 | bufferptr v; | |
11fdf7f2 | 375 | int r = fs->store->getattr(ch, oid, key.c_str(), v); |
7c673cae FG |
376 | if (r == -ENODATA) |
377 | r = -ENOENT; | |
378 | if (r < 0) | |
379 | return r; | |
380 | stbuf->st_size = v.length(); | |
381 | } | |
382 | break; | |
383 | ||
384 | default: | |
385 | return -ENOENT; | |
386 | } | |
387 | ||
388 | return 0; | |
389 | } | |
390 | ||
391 | static int os_readdir(const char *path, | |
392 | void *buf, | |
393 | fuse_fill_dir_t filler, | |
394 | off_t offset, | |
1911f103 TL |
395 | struct fuse_file_info *fi |
396 | #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0) | |
397 | , enum fuse_readdir_flags | |
398 | #endif | |
399 | ) | |
7c673cae FG |
400 | { |
401 | fuse_context *fc = fuse_get_context(); | |
402 | FuseStore *fs = static_cast<FuseStore*>(fc->private_data); | |
403 | ldout(fs->store->cct, 10) << __func__ << " " << path << " offset " << offset | |
404 | << dendl; | |
405 | coll_t cid; | |
406 | ghobject_t oid; | |
407 | string key; | |
408 | uint32_t hash_value, hash_bits; | |
409 | int t = parse_fn(fs->store->cct, path, &cid, &oid, &key, &hash_value, | |
410 | &hash_bits); | |
411 | if (t < 0) | |
412 | return t; | |
413 | ||
414 | std::lock_guard<std::mutex> l(fs->lock); | |
415 | ||
11fdf7f2 TL |
416 | auto ch = fs->store->open_collection(cid); |
417 | ||
7c673cae FG |
418 | // we can't shift 32 bits or else off_t will go negative |
419 | const int hash_shift = 31; | |
420 | ||
421 | switch (t) { | |
422 | case FN_ROOT: | |
423 | { | |
1911f103 | 424 | filler_compat(filler, buf, "type", NULL, 0); |
7c673cae FG |
425 | vector<coll_t> cls; |
426 | fs->store->list_collections(cls); | |
427 | for (auto c : cls) { | |
1911f103 | 428 | int r = filler_compat(filler, buf, stringify(c).c_str(), NULL, 0); |
7c673cae FG |
429 | if (r > 0) |
430 | break; | |
431 | } | |
432 | } | |
433 | break; | |
434 | ||
435 | case FN_COLLECTION: | |
436 | { | |
11fdf7f2 TL |
437 | if (!ch) { |
438 | return -ENOENT; | |
439 | } | |
1911f103 | 440 | filler_compat(filler, buf, "bitwise_hash_start", NULL, 0); |
11fdf7f2 | 441 | if (fs->store->collection_bits(ch) >= 0) { |
1911f103 TL |
442 | filler_compat(filler, buf, "bitwise_hash_end", NULL, 0); |
443 | filler_compat(filler, buf, "bitwise_hash_bits", NULL, 0); | |
7c673cae | 444 | } |
1911f103 TL |
445 | filler_compat(filler, buf, "all", NULL, 0); |
446 | filler_compat(filler, buf, "by_bitwise_hash", NULL, 0); | |
7c673cae FG |
447 | spg_t pgid; |
448 | if (cid.is_pg(&pgid) && | |
11fdf7f2 | 449 | fs->store->exists(ch, pgid.make_pgmeta_oid())) { |
1911f103 | 450 | filler_compat(filler, buf, "pgmeta", NULL, 0); |
7c673cae FG |
451 | } |
452 | } | |
453 | break; | |
454 | ||
455 | case FN_OBJECT: | |
456 | { | |
1911f103 TL |
457 | filler_compat(filler, buf, "bitwise_hash", NULL, 0); |
458 | filler_compat(filler, buf, "data", NULL, 0); | |
459 | filler_compat(filler, buf, "omap", NULL, 0); | |
460 | filler_compat(filler, buf, "attr", NULL, 0); | |
461 | filler_compat(filler, buf, "omap_header", NULL, 0); | |
7c673cae FG |
462 | } |
463 | break; | |
464 | ||
465 | case FN_HASH_VAL: | |
466 | case FN_ALL: | |
467 | { | |
468 | uint32_t bitwise_hash = (offset >> hash_shift) & 0xffffffff; | |
469 | uint32_t hashoff = offset - (bitwise_hash << hash_shift); | |
470 | int skip = hashoff; | |
471 | ghobject_t next = cid.get_min_hobj(); | |
472 | if (offset) { | |
473 | // obey the offset | |
474 | next.hobj.set_hash(hobject_t::_reverse_bits(bitwise_hash)); | |
475 | } else if (t == FN_HASH_VAL) { | |
476 | next.hobj.set_hash(hobject_t::_reverse_bits(hash_value)); | |
477 | } | |
478 | ghobject_t last; | |
479 | if (t == FN_HASH_VAL) { | |
480 | last = next; | |
481 | uint64_t rev_end = (hash_value | (0xffffffff >> hash_bits)) + 1; | |
482 | if (rev_end >= 0x100000000) | |
483 | last = ghobject_t::get_max(); | |
484 | else | |
485 | last.hobj.set_hash(hobject_t::_reverse_bits(rev_end)); | |
486 | } else { | |
487 | last = ghobject_t::get_max(); | |
488 | } | |
489 | ldout(fs->store->cct, 10) << __func__ << std::hex | |
490 | << " offset " << offset << " hash " | |
491 | << hobject_t::_reverse_bits(hash_value) | |
492 | << std::dec | |
493 | << "/" << hash_bits | |
494 | << " first " << next << " last " << last | |
495 | << dendl; | |
496 | while (true) { | |
497 | vector<ghobject_t> ls; | |
498 | int r = fs->store->collection_list( | |
11fdf7f2 | 499 | ch, next, last, 1000, &ls, &next); |
7c673cae FG |
500 | if (r < 0) |
501 | return r; | |
502 | for (auto p : ls) { | |
503 | if (skip) { | |
504 | --skip; | |
505 | continue; | |
506 | } | |
507 | uint32_t cur_bitwise_hash = p.hobj.get_bitwise_key_u32(); | |
508 | if (cur_bitwise_hash != bitwise_hash) { | |
509 | bitwise_hash = cur_bitwise_hash; | |
510 | hashoff = 0; | |
511 | } | |
512 | ++hashoff; | |
513 | uint64_t cur_off = ((uint64_t)bitwise_hash << hash_shift) | | |
514 | (uint64_t)hashoff; | |
515 | string s = stringify(p); | |
1911f103 | 516 | r = filler_compat(filler, buf, s.c_str(), NULL, cur_off); |
7c673cae FG |
517 | if (r) |
518 | break; | |
519 | } | |
520 | if (r) | |
521 | break; | |
522 | if (next == ghobject_t::get_max() || next == last) | |
523 | break; | |
524 | } | |
525 | } | |
526 | break; | |
527 | ||
528 | case FN_OBJECT_OMAP: | |
529 | { | |
530 | set<string> keys; | |
11fdf7f2 | 531 | fs->store->omap_get_keys(ch, oid, &keys); |
7c673cae FG |
532 | unsigned skip = offset; |
533 | for (auto k : keys) { | |
534 | if (skip) { | |
535 | --skip; | |
536 | continue; | |
537 | } | |
538 | ++offset; | |
1911f103 | 539 | int r = filler_compat(filler, buf, k.c_str(), NULL, offset); |
7c673cae FG |
540 | if (r) |
541 | break; | |
542 | } | |
543 | } | |
544 | break; | |
545 | ||
546 | case FN_OBJECT_ATTR: | |
547 | { | |
548 | map<string,bufferptr> aset; | |
11fdf7f2 | 549 | fs->store->getattrs(ch, oid, aset); |
7c673cae FG |
550 | unsigned skip = offset; |
551 | for (auto a : aset) { | |
552 | if (skip) { | |
553 | --skip; | |
554 | continue; | |
555 | } | |
556 | ++offset; | |
1911f103 | 557 | int r = filler_compat(filler, buf, a.first.c_str(), NULL, offset); |
7c673cae FG |
558 | if (r) |
559 | break; | |
560 | } | |
561 | } | |
562 | break; | |
563 | } | |
564 | return 0; | |
565 | } | |
566 | ||
567 | static int os_open(const char *path, struct fuse_file_info *fi) | |
568 | { | |
569 | fuse_context *fc = fuse_get_context(); | |
570 | FuseStore *fs = static_cast<FuseStore*>(fc->private_data); | |
571 | ldout(fs->store->cct, 10) << __func__ << " " << path << dendl; | |
572 | coll_t cid; | |
573 | ghobject_t oid; | |
574 | string key; | |
575 | uint32_t hash_value, hash_bits; | |
576 | int t = parse_fn(fs->store->cct, path, &cid, &oid, &key, &hash_value, | |
577 | &hash_bits); | |
578 | if (t < 0) | |
579 | return t; | |
580 | ||
581 | std::lock_guard<std::mutex> l(fs->lock); | |
582 | ||
11fdf7f2 TL |
583 | auto ch = fs->store->open_collection(cid); |
584 | ||
7c673cae FG |
585 | bufferlist *pbl = 0; |
586 | switch (t) { | |
587 | case FN_TYPE: | |
588 | pbl = new bufferlist; | |
589 | pbl->append(fs->store->get_type()); | |
590 | pbl->append("\n"); | |
591 | break; | |
592 | ||
593 | case FN_HASH_START: | |
594 | { | |
595 | pbl = new bufferlist; | |
596 | spg_t pgid; | |
597 | if (cid.is_pg(&pgid)) { | |
598 | unsigned long h; | |
599 | h = hobject_t::_reverse_bits(pgid.ps()); | |
600 | char buf[10]; | |
601 | snprintf(buf, sizeof(buf), "%08lx\n", h); | |
602 | pbl->append(buf); | |
603 | } else { | |
604 | pbl->append("00000000\n"); | |
605 | } | |
606 | } | |
607 | break; | |
608 | ||
609 | case FN_HASH_END: | |
610 | { | |
11fdf7f2 TL |
611 | if (!ch) { |
612 | return -ENOENT; | |
613 | } | |
7c673cae FG |
614 | spg_t pgid; |
615 | unsigned long h; | |
616 | if (cid.is_pg(&pgid)) { | |
11fdf7f2 | 617 | int hash_bits = fs->store->collection_bits(ch); |
7c673cae FG |
618 | if (hash_bits >= 0) { |
619 | uint64_t rev_start = hobject_t::_reverse_bits(pgid.ps()); | |
620 | uint64_t rev_end = (rev_start | (0xffffffff >> hash_bits)); | |
621 | h = rev_end; | |
622 | } else { | |
623 | return -ENOENT; | |
624 | } | |
625 | } else { | |
626 | h = 0xffffffff; | |
627 | } | |
628 | char buf[10]; | |
629 | snprintf(buf, sizeof(buf), "%08lx\n", h); | |
630 | pbl = new bufferlist; | |
631 | pbl->append(buf); | |
632 | } | |
633 | break; | |
634 | ||
635 | case FN_HASH_BITS: | |
636 | { | |
11fdf7f2 TL |
637 | if (!ch) { |
638 | return -ENOENT; | |
639 | } | |
640 | int r = fs->store->collection_bits(ch); | |
7c673cae FG |
641 | if (r < 0) |
642 | return r; | |
11fdf7f2 | 643 | char buf[12]; |
7c673cae FG |
644 | snprintf(buf, sizeof(buf), "%d\n", r); |
645 | pbl = new bufferlist; | |
646 | pbl->append(buf); | |
647 | } | |
648 | break; | |
649 | ||
650 | case FN_OBJECT_HASH: | |
651 | { | |
652 | pbl = new bufferlist; | |
653 | char buf[10]; | |
654 | snprintf(buf, sizeof(buf), "%08x\n", | |
655 | (unsigned)oid.hobj.get_bitwise_key_u32()); | |
656 | pbl->append(buf); | |
657 | } | |
658 | break; | |
659 | ||
660 | case FN_OBJECT_DATA: | |
661 | { | |
662 | int r = fs->open_file( | |
663 | path, fi, | |
664 | [&](bufferlist *pbl) { | |
11fdf7f2 | 665 | return fs->store->read(ch, oid, 0, 0, *pbl); |
7c673cae FG |
666 | }); |
667 | if (r < 0) { | |
668 | return r; | |
669 | } | |
670 | } | |
671 | break; | |
672 | ||
673 | case FN_OBJECT_ATTR_VAL: | |
674 | { | |
675 | int r = fs->open_file( | |
676 | path, fi, | |
677 | [&](bufferlist *pbl) { | |
678 | bufferptr bp; | |
11fdf7f2 | 679 | int r = fs->store->getattr(ch, oid, key.c_str(), bp); |
7c673cae FG |
680 | if (r < 0) |
681 | return r; | |
682 | pbl->append(bp); | |
683 | return 0; | |
684 | }); | |
685 | if (r < 0) | |
686 | return r; | |
687 | } | |
688 | break; | |
689 | ||
690 | case FN_OBJECT_OMAP_VAL: | |
691 | { | |
692 | int r = fs->open_file( | |
693 | path, fi, | |
694 | [&](bufferlist *pbl) { | |
695 | set<string> k; | |
696 | k.insert(key); | |
697 | map<string,bufferlist> v; | |
11fdf7f2 | 698 | int r = fs->store->omap_get_values(ch, oid, k, &v); |
7c673cae FG |
699 | if (r < 0) |
700 | return r; | |
701 | *pbl = v[key]; | |
702 | return 0; | |
703 | }); | |
704 | if (r < 0) | |
705 | return r; | |
706 | } | |
707 | break; | |
708 | ||
709 | case FN_OBJECT_OMAP_HEADER: | |
710 | { | |
711 | int r = fs->open_file( | |
712 | path, fi, | |
713 | [&](bufferlist *pbl) { | |
11fdf7f2 | 714 | return fs->store->omap_get_header(ch, oid, pbl); |
7c673cae FG |
715 | }); |
716 | if (r < 0) | |
717 | return r; | |
718 | } | |
719 | break; | |
720 | } | |
721 | ||
722 | if (pbl) { | |
723 | FuseStore::OpenFile *o = new FuseStore::OpenFile; | |
724 | o->bl.claim(*pbl); | |
725 | fi->fh = reinterpret_cast<uint64_t>(o); | |
726 | } | |
727 | return 0; | |
728 | } | |
729 | ||
730 | static int os_mkdir(const char *path, mode_t mode) | |
731 | { | |
732 | fuse_context *fc = fuse_get_context(); | |
733 | FuseStore *fs = static_cast<FuseStore*>(fc->private_data); | |
734 | ldout(fs->store->cct, 10) << __func__ << " " << path << dendl; | |
735 | coll_t cid; | |
736 | ghobject_t oid; | |
737 | string key; | |
738 | uint32_t hash_value, hash_bits; | |
739 | int f = parse_fn(fs->store->cct, path, &cid, &oid, &key, &hash_value, | |
740 | &hash_bits); | |
741 | if (f < 0) | |
742 | return f; | |
743 | ||
744 | std::lock_guard<std::mutex> l(fs->lock); | |
745 | ||
11fdf7f2 TL |
746 | ObjectStore::CollectionHandle ch; |
747 | ||
7c673cae FG |
748 | ObjectStore::Transaction t; |
749 | switch (f) { | |
750 | case FN_OBJECT: | |
751 | { | |
11fdf7f2 TL |
752 | ch = fs->store->open_collection(cid); |
753 | if (!ch) { | |
754 | return -ENOENT; | |
755 | } | |
7c673cae FG |
756 | spg_t pgid; |
757 | if (cid.is_pg(&pgid)) { | |
11fdf7f2 | 758 | int bits = fs->store->collection_bits(ch); |
7c673cae FG |
759 | if (bits >= 0 && !oid.match(bits, pgid.ps())) { |
760 | // sorry, not part of this PG | |
761 | return -EINVAL; | |
762 | } | |
763 | } | |
764 | t.touch(cid, oid); | |
11fdf7f2 | 765 | ch = fs->store->open_collection(cid); |
7c673cae FG |
766 | } |
767 | break; | |
768 | ||
769 | case FN_COLLECTION: | |
770 | if (cid.is_pg()) { | |
771 | // use the mode for the bit count. e.g., mkdir --mode=0003 | |
772 | // mnt/0.7_head will create 0.7 with bits = 3. | |
773 | mode &= 0777; | |
774 | if (mode >= 32) | |
775 | return -EINVAL; | |
776 | } else { | |
777 | mode = 0; | |
778 | } | |
779 | t.create_collection(cid, mode); | |
11fdf7f2 | 780 | ch = fs->store->create_new_collection(cid); |
7c673cae FG |
781 | break; |
782 | ||
783 | default: | |
784 | return -EPERM; | |
785 | } | |
786 | ||
787 | if (!t.empty()) { | |
11fdf7f2 | 788 | fs->store->queue_transaction(ch, std::move(t)); |
7c673cae FG |
789 | } |
790 | ||
791 | return 0; | |
792 | } | |
793 | ||
1911f103 TL |
794 | static int os_chmod(const char *path, mode_t mode |
795 | #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0) | |
796 | , struct fuse_file_info *fi | |
797 | #endif | |
798 | ) | |
7c673cae FG |
799 | { |
800 | fuse_context *fc = fuse_get_context(); | |
801 | FuseStore *fs = static_cast<FuseStore*>(fc->private_data); | |
802 | ldout(fs->store->cct, 10) << __func__ << " " << path << dendl; | |
803 | return 0; | |
804 | } | |
805 | ||
806 | static int os_create(const char *path, mode_t mode, struct fuse_file_info *fi) | |
807 | { | |
808 | fuse_context *fc = fuse_get_context(); | |
809 | FuseStore *fs = static_cast<FuseStore*>(fc->private_data); | |
810 | ldout(fs->store->cct, 10) << __func__ << " " << path << dendl; | |
811 | coll_t cid; | |
812 | ghobject_t oid; | |
813 | string key; | |
814 | uint32_t hash_value, hash_bits; | |
815 | int f = parse_fn(fs->store->cct, path, &cid, &oid, &key, &hash_value, | |
816 | &hash_bits); | |
817 | if (f < 0) | |
818 | return f; | |
819 | ||
820 | std::lock_guard<std::mutex> l(fs->lock); | |
821 | ||
11fdf7f2 TL |
822 | ObjectStore::CollectionHandle ch = fs->store->open_collection(cid); |
823 | ||
7c673cae FG |
824 | ObjectStore::Transaction t; |
825 | bufferlist *pbl = 0; | |
826 | switch (f) { | |
827 | case FN_OBJECT_DATA: | |
828 | { | |
829 | pbl = new bufferlist; | |
11fdf7f2 | 830 | fs->store->read(ch, oid, 0, 0, *pbl); |
7c673cae FG |
831 | } |
832 | break; | |
833 | ||
834 | case FN_OBJECT_ATTR_VAL: | |
835 | { | |
836 | pbl = new bufferlist; | |
837 | bufferptr bp; | |
11fdf7f2 | 838 | int r = fs->store->getattr(ch, oid, key.c_str(), bp); |
7c673cae FG |
839 | if (r == -ENODATA) { |
840 | bufferlist empty; | |
841 | t.setattr(cid, oid, key.c_str(), empty); | |
842 | } | |
843 | pbl->append(bp); | |
844 | } | |
845 | break; | |
846 | ||
847 | case FN_OBJECT_OMAP_VAL: | |
848 | { | |
849 | pbl = new bufferlist; | |
850 | set<string> k; | |
851 | k.insert(key); | |
852 | map<string,bufferlist> v; | |
11fdf7f2 | 853 | fs->store->omap_get_values(ch, oid, k, &v); |
7c673cae FG |
854 | if (v.count(key) == 0) { |
855 | map<string,bufferlist> aset; | |
856 | aset[key] = bufferlist(); | |
857 | t.omap_setkeys(cid, oid, aset); | |
858 | } else { | |
859 | *pbl = v[key]; | |
860 | } | |
861 | } | |
862 | break; | |
863 | } | |
864 | ||
865 | if (!t.empty()) { | |
11fdf7f2 | 866 | fs->store->queue_transaction(ch, std::move(t)); |
7c673cae FG |
867 | } |
868 | ||
869 | if (pbl) { | |
870 | FuseStore::OpenFile *o = new FuseStore::OpenFile; | |
871 | o->bl.claim(*pbl); | |
872 | o->dirty = true; | |
873 | fi->fh = reinterpret_cast<uint64_t>(o); | |
874 | } | |
875 | return 0; | |
876 | } | |
877 | ||
878 | static int os_release(const char *path, struct fuse_file_info *fi) | |
879 | { | |
880 | fuse_context *fc = fuse_get_context(); | |
881 | FuseStore *fs = static_cast<FuseStore*>(fc->private_data); | |
882 | ldout(fs->store->cct, 10) << __func__ << " " << path << dendl; | |
883 | std::lock_guard<std::mutex> l(fs->lock); | |
884 | FuseStore::OpenFile *o = reinterpret_cast<FuseStore::OpenFile*>(fi->fh); | |
885 | if (--o->ref == 0) { | |
886 | ldout(fs->store->cct, 10) << __func__ << " closing last " << o->path << dendl; | |
887 | fs->open_files.erase(o->path); | |
888 | delete o; | |
889 | } | |
890 | return 0; | |
891 | } | |
892 | ||
893 | static int os_read(const char *path, char *buf, size_t size, off_t offset, | |
894 | struct fuse_file_info *fi) | |
895 | { | |
896 | fuse_context *fc = fuse_get_context(); | |
897 | FuseStore *fs = static_cast<FuseStore*>(fc->private_data); | |
898 | ldout(fs->store->cct, 10) << __func__ << " " << path << " offset " << offset | |
899 | << " size " << size << dendl; | |
900 | std::lock_guard<std::mutex> l(fs->lock); | |
901 | FuseStore::OpenFile *o = reinterpret_cast<FuseStore::OpenFile*>(fi->fh); | |
902 | if (!o) | |
903 | return 0; | |
904 | if (offset >= o->bl.length()) | |
905 | return 0; | |
906 | if (offset + size > o->bl.length()) | |
907 | size = o->bl.length() - offset; | |
908 | bufferlist r; | |
909 | r.substr_of(o->bl, offset, size); | |
910 | memcpy(buf, r.c_str(), r.length()); | |
911 | return r.length(); | |
912 | } | |
913 | ||
914 | static int os_write(const char *path, const char *buf, size_t size, | |
915 | off_t offset, struct fuse_file_info *fi) | |
916 | { | |
917 | fuse_context *fc = fuse_get_context(); | |
918 | FuseStore *fs = static_cast<FuseStore*>(fc->private_data); | |
919 | ldout(fs->store->cct, 10) << __func__ << " " << path << " offset " << offset | |
920 | << " size " << size << dendl; | |
921 | std::lock_guard<std::mutex> l(fs->lock); | |
922 | FuseStore::OpenFile *o = reinterpret_cast<FuseStore::OpenFile*>(fi->fh); | |
923 | if (!o) | |
924 | return 0; | |
925 | ||
926 | bufferlist final; | |
927 | if (offset) { | |
928 | if (offset > o->bl.length()) { | |
929 | final.substr_of(o->bl, 0, offset); | |
930 | } else { | |
931 | final.claim_append(o->bl); | |
932 | size_t zlen = offset - final.length(); | |
933 | final.append_zero(zlen); | |
934 | } | |
935 | } | |
936 | final.append(buf, size); | |
937 | if (offset + size < o->bl.length()) { | |
938 | bufferlist rest; | |
939 | rest.substr_of(o->bl, offset + size, o->bl.length() - offset - size); | |
940 | final.claim_append(rest); | |
941 | } | |
942 | o->bl = final; | |
943 | o->dirty = true; | |
944 | return size; | |
945 | } | |
946 | ||
947 | int os_flush(const char *path, struct fuse_file_info *fi) | |
948 | { | |
949 | fuse_context *fc = fuse_get_context(); | |
950 | FuseStore *fs = static_cast<FuseStore*>(fc->private_data); | |
951 | ldout(fs->store->cct, 10) << __func__ << " " << path << dendl; | |
952 | coll_t cid; | |
953 | ghobject_t oid; | |
954 | string key; | |
955 | uint32_t hash_value, hash_bits; | |
956 | int f = parse_fn(fs->store->cct, path, &cid, &oid, &key, &hash_value, | |
957 | &hash_bits); | |
958 | if (f < 0) | |
959 | return f; | |
960 | ||
961 | std::lock_guard<std::mutex> l(fs->lock); | |
962 | ||
963 | FuseStore::OpenFile *o = reinterpret_cast<FuseStore::OpenFile*>(fi->fh); | |
964 | if (!o) | |
965 | return 0; | |
966 | if (!o->dirty) | |
967 | return 0; | |
968 | ||
11fdf7f2 TL |
969 | ObjectStore::CollectionHandle ch = fs->store->open_collection(cid); |
970 | ||
7c673cae FG |
971 | ObjectStore::Transaction t; |
972 | ||
973 | switch (f) { | |
974 | case FN_OBJECT_DATA: | |
975 | t.write(cid, oid, 0, o->bl.length(), o->bl); | |
976 | break; | |
977 | ||
978 | case FN_OBJECT_ATTR_VAL: | |
979 | t.setattr(cid, oid, key.c_str(), o->bl); | |
980 | break; | |
981 | ||
982 | case FN_OBJECT_OMAP_VAL: | |
983 | { | |
984 | map<string,bufferlist> aset; | |
985 | aset[key] = o->bl; | |
986 | t.omap_setkeys(cid, oid, aset); | |
987 | break; | |
988 | } | |
989 | ||
990 | case FN_OBJECT_OMAP_HEADER: | |
991 | t.omap_setheader(cid, oid, o->bl); | |
992 | break; | |
993 | ||
994 | default: | |
995 | return 0; | |
996 | } | |
997 | ||
11fdf7f2 | 998 | fs->store->queue_transaction(ch, std::move(t)); |
7c673cae FG |
999 | |
1000 | return 0; | |
1001 | } | |
1002 | ||
1003 | static int os_unlink(const char *path) | |
1004 | { | |
1005 | fuse_context *fc = fuse_get_context(); | |
1006 | FuseStore *fs = static_cast<FuseStore*>(fc->private_data); | |
1007 | ldout(fs->store->cct, 10) << __func__ << " " << path << dendl; | |
1008 | coll_t cid; | |
1009 | ghobject_t oid; | |
1010 | string key; | |
1011 | uint32_t hash_value, hash_bits; | |
1012 | int f = parse_fn(fs->store->cct, path, &cid, &oid, &key, &hash_value, | |
1013 | &hash_bits); | |
1014 | if (f < 0) | |
1015 | return f; | |
1016 | ||
1017 | std::lock_guard<std::mutex> l(fs->lock); | |
1018 | ||
11fdf7f2 | 1019 | ObjectStore::CollectionHandle ch = fs->store->open_collection(cid); |
7c673cae FG |
1020 | ObjectStore::Transaction t; |
1021 | ||
1022 | switch (f) { | |
1023 | case FN_OBJECT_OMAP_VAL: | |
1024 | { | |
9f95a23c | 1025 | t.omap_rmkey(cid, oid, key); |
7c673cae FG |
1026 | } |
1027 | break; | |
1028 | ||
1029 | case FN_OBJECT_ATTR_VAL: | |
1030 | t.rmattr(cid, oid, key.c_str()); | |
1031 | break; | |
1032 | ||
1033 | case FN_OBJECT_OMAP_HEADER: | |
1034 | { | |
1035 | bufferlist empty; | |
1036 | t.omap_setheader(cid, oid, empty); | |
1037 | } | |
1038 | break; | |
1039 | ||
1040 | case FN_OBJECT: | |
1041 | t.remove(cid, oid); | |
1042 | break; | |
1043 | ||
1044 | case FN_COLLECTION: | |
1045 | { | |
1046 | bool empty; | |
11fdf7f2 | 1047 | int r = fs->store->collection_empty(ch, &empty); |
7c673cae FG |
1048 | if (r < 0) |
1049 | return r; | |
1050 | if (!empty) | |
1051 | return -ENOTEMPTY; | |
1052 | t.remove_collection(cid); | |
1053 | } | |
1054 | break; | |
1055 | ||
1056 | case FN_OBJECT_DATA: | |
1057 | t.truncate(cid, oid, 0); | |
1058 | break; | |
1059 | ||
1060 | default: | |
1061 | return -EPERM; | |
1062 | } | |
1063 | ||
11fdf7f2 | 1064 | fs->store->queue_transaction(ch, std::move(t)); |
7c673cae FG |
1065 | |
1066 | return 0; | |
1067 | } | |
1068 | ||
1911f103 TL |
1069 | static int os_truncate(const char *path, off_t size |
1070 | #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0) | |
1071 | , struct fuse_file_info *fi | |
1072 | #endif | |
1073 | ) | |
7c673cae FG |
1074 | { |
1075 | fuse_context *fc = fuse_get_context(); | |
1076 | FuseStore *fs = static_cast<FuseStore*>(fc->private_data); | |
1077 | ldout(fs->store->cct, 10) << __func__ << " " << path << " size " << size << dendl; | |
1078 | coll_t cid; | |
1079 | ghobject_t oid; | |
1080 | string key; | |
1081 | uint32_t hash_value, hash_bits; | |
1082 | int f = parse_fn(fs->store->cct, path, &cid, &oid, &key, &hash_value, | |
1083 | &hash_bits); | |
1084 | if (f < 0) | |
1085 | return f; | |
1086 | ||
1087 | if (f == FN_OBJECT_OMAP_VAL || | |
1088 | f == FN_OBJECT_ATTR_VAL || | |
1089 | f == FN_OBJECT_OMAP_HEADER) { | |
1090 | if (size) | |
1091 | return -EPERM; | |
1092 | return 0; | |
1093 | } | |
1094 | if (f != FN_OBJECT_DATA) | |
1095 | return -EPERM; | |
1096 | ||
1097 | std::lock_guard<std::mutex> l(fs->lock); | |
1098 | ||
1099 | if (fs->open_files.count(path)) { | |
1100 | FuseStore::OpenFile *o = fs->open_files[path]; | |
1101 | if (o->bl.length() > size) { | |
1102 | bufferlist t; | |
1103 | t.substr_of(o->bl, 0, size); | |
1104 | o->bl.swap(t); | |
1105 | } | |
1106 | } | |
1107 | ||
11fdf7f2 | 1108 | ObjectStore::CollectionHandle ch = fs->store->open_collection(cid); |
7c673cae FG |
1109 | ObjectStore::Transaction t; |
1110 | t.truncate(cid, oid, size); | |
11fdf7f2 | 1111 | fs->store->queue_transaction(ch, std::move(t)); |
7c673cae FG |
1112 | return 0; |
1113 | } | |
1114 | ||
1115 | static int os_statfs(const char *path, struct statvfs *stbuf) | |
1116 | { | |
1117 | fuse_context *fc = fuse_get_context(); | |
1118 | FuseStore *fs = static_cast<FuseStore*>(fc->private_data); | |
1119 | ldout(fs->store->cct, 10) << __func__ << " " << path << dendl; | |
1120 | std::lock_guard<std::mutex> l(fs->lock); | |
1121 | ||
1122 | struct store_statfs_t s; | |
1123 | int r = fs->store->statfs(&s); | |
1124 | if (r < 0) | |
1125 | return r; | |
1126 | stbuf->f_bsize = 4096; // LIES! | |
1127 | stbuf->f_blocks = s.total / 4096; | |
1128 | stbuf->f_bavail = s.available / 4096; | |
11fdf7f2 | 1129 | stbuf->f_bfree = stbuf->f_bavail; |
7c673cae | 1130 | |
11fdf7f2 TL |
1131 | ldout(fs->store->cct, 10) << __func__ << " " << path << ": " |
1132 | << stbuf->f_bavail << "/" << stbuf->f_blocks << dendl; | |
7c673cae FG |
1133 | return 0; |
1134 | } | |
1135 | ||
1136 | static struct fuse_operations fs_oper = { | |
1137 | getattr: os_getattr, | |
1138 | readlink: 0, | |
1911f103 | 1139 | #if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0) |
7c673cae | 1140 | getdir: 0, |
1911f103 | 1141 | #endif |
7c673cae FG |
1142 | mknod: 0, |
1143 | mkdir: os_mkdir, | |
1144 | unlink: os_unlink, | |
1145 | rmdir: os_unlink, | |
1146 | symlink: 0, | |
1147 | rename: 0, | |
1148 | link: 0, | |
1149 | chmod: os_chmod, | |
1150 | chown: 0, | |
1151 | truncate: os_truncate, | |
1911f103 | 1152 | #if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0) |
7c673cae | 1153 | utime: 0, |
1911f103 | 1154 | #endif |
7c673cae FG |
1155 | open: os_open, |
1156 | read: os_read, | |
1157 | write: os_write, | |
1158 | statfs: os_statfs, | |
1159 | flush: os_flush, | |
1160 | release: os_release, | |
1161 | fsync: 0, | |
1162 | setxattr: 0, | |
1163 | getxattr: 0, | |
1164 | listxattr: 0, | |
1165 | removexattr: 0, | |
1166 | opendir: 0, | |
1167 | readdir: os_readdir, | |
1168 | releasedir: 0, | |
1169 | fsyncdir: 0, | |
1170 | init: 0, | |
1171 | destroy: 0, | |
1172 | access: 0, | |
1173 | create: os_create, | |
1174 | }; | |
1175 | ||
1176 | int FuseStore::main() | |
1177 | { | |
1178 | const char *v[] = { | |
1179 | "foo", | |
1180 | mount_point.c_str(), | |
1181 | "-f", | |
1182 | "-d", // debug | |
1183 | }; | |
1184 | int c = 3; | |
11fdf7f2 TL |
1185 | auto fuse_debug = store->cct->_conf.get_val<bool>("fuse_debug"); |
1186 | if (fuse_debug) | |
7c673cae FG |
1187 | ++c; |
1188 | return fuse_main(c, (char**)v, &fs_oper, (void*)this); | |
1189 | } | |
1190 | ||
1191 | int FuseStore::start() | |
1192 | { | |
1193 | dout(10) << __func__ << dendl; | |
1194 | ||
1195 | memset(&info->args, 0, sizeof(info->args)); | |
1196 | const char *v[] = { | |
1197 | "foo", | |
1198 | mount_point.c_str(), | |
1199 | "-f", // foreground | |
1200 | "-d", // debug | |
1201 | }; | |
1202 | int c = 3; | |
1911f103 TL |
1203 | #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0) |
1204 | int rc; | |
1205 | struct fuse_cmdline_opts opts = {}; | |
1206 | #endif | |
11fdf7f2 TL |
1207 | auto fuse_debug = store->cct->_conf.get_val<bool>("fuse_debug"); |
1208 | if (fuse_debug) | |
7c673cae FG |
1209 | ++c; |
1210 | fuse_args a = FUSE_ARGS_INIT(c, (char**)v); | |
1211 | info->args = a; | |
1911f103 TL |
1212 | #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0) |
1213 | if (fuse_parse_cmdline(&info->args, &opts) == -1) { | |
1214 | #else | |
7c673cae | 1215 | if (fuse_parse_cmdline(&info->args, &info->mountpoint, NULL, NULL) == -1) { |
1911f103 | 1216 | #endif |
7c673cae FG |
1217 | derr << __func__ << " failed to parse args" << dendl; |
1218 | return -EINVAL; | |
1219 | } | |
1220 | ||
1911f103 TL |
1221 | #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0) |
1222 | info->mountpoint = opts.mountpoint; | |
1223 | info->f = fuse_new(&info->args, &fs_oper, sizeof(fs_oper), (void*)this); | |
1224 | if (!info->f) { | |
1225 | derr << __func__ << " fuse_new failed" << dendl; | |
1226 | return -EIO; | |
1227 | } | |
1228 | ||
1229 | rc = fuse_mount(info->f, info->mountpoint); | |
1230 | if (rc != 0) { | |
1231 | derr << __func__ << " fuse_mount failed" << dendl; | |
1232 | return -EIO; | |
1233 | } | |
1234 | #else | |
7c673cae FG |
1235 | info->ch = fuse_mount(info->mountpoint, &info->args); |
1236 | if (!info->ch) { | |
1237 | derr << __func__ << " fuse_mount failed" << dendl; | |
1238 | return -EIO; | |
1239 | } | |
1240 | ||
1241 | info->f = fuse_new(info->ch, &info->args, &fs_oper, sizeof(fs_oper), | |
1242 | (void*)this); | |
1243 | if (!info->f) { | |
1244 | fuse_unmount(info->mountpoint, info->ch); | |
1245 | derr << __func__ << " fuse_new failed" << dendl; | |
1246 | return -EIO; | |
1247 | } | |
1911f103 | 1248 | #endif |
7c673cae FG |
1249 | |
1250 | fuse_thread.create("fusestore"); | |
1251 | dout(10) << __func__ << " done" << dendl; | |
1252 | return 0; | |
1253 | } | |
1254 | ||
1255 | int FuseStore::loop() | |
1256 | { | |
1257 | dout(10) << __func__ << " enter" << dendl; | |
1258 | int r = fuse_loop(info->f); | |
1259 | if (r) | |
1260 | derr << __func__ << " got " << cpp_strerror(r) << dendl; | |
1261 | dout(10) << __func__ << " exit" << dendl; | |
1262 | return r; | |
1263 | } | |
1264 | ||
1265 | int FuseStore::stop() | |
1266 | { | |
1267 | dout(10) << __func__ << " enter" << dendl; | |
1911f103 TL |
1268 | #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0) |
1269 | fuse_unmount(info->f); | |
1270 | #else | |
7c673cae | 1271 | fuse_unmount(info->mountpoint, info->ch); |
1911f103 | 1272 | #endif |
7c673cae FG |
1273 | fuse_thread.join(); |
1274 | fuse_destroy(info->f); | |
1275 | dout(10) << __func__ << " exit" << dendl; | |
1276 | return 0; | |
1277 | } |