]>
git.proxmox.com Git - ceph.git/blob - ceph/src/os/FuseStore.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "include/compat.h"
6 #include "os/ObjectStore.h"
7 #include "include/stringify.h"
8 #include "common/errno.h"
10 #define FUSE_USE_VERSION 30
12 #include <fuse_lowlevel.h>
13 #include "include/ceph_fuse.h"
15 #include <sys/types.h>
18 #include <fcntl.h> /* Definition of AT_* constants */
21 #if defined(__APPLE__) || defined(__FreeBSD__)
22 #include <sys/param.h>
23 #include <sys/mount.h>
26 #define dout_context store->cct
27 #define dout_subsys ceph_subsys_fuse
28 #include "common/debug.h"
30 #define dout_prefix *_dout << "fuse "
32 // some fuse-y bits of state
34 struct fuse_args args
;
36 #if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
42 int FuseStore::open_file(string p
, struct fuse_file_info
*fi
,
43 std::function
<int(bufferlist
*bl
)> f
)
45 if (open_files
.count(p
)) {
46 OpenFile
*o
= open_files
[p
];
47 fi
->fh
= reinterpret_cast<uint64_t>(o
);
56 OpenFile
*o
= new OpenFile
;
60 fi
->fh
= reinterpret_cast<uint64_t>(o
);
65 FuseStore::FuseStore(ObjectStore
*s
, string p
)
73 FuseStore::~FuseStore()
81 * $cid/type - objectstore type
82 * $cid/bitwise_hash_start = lowest hash value
83 * $cid/bitwise_hash_end = highest hash value
84 * $cid/bitwise_hash_bits - how many bits are significant
85 * $cid/pgmeta/ - pgmeta object
86 * $cid/all/ - all objects
88 * $cid/all/$obj/bitwise_hash
90 * $cid/all/$obj/omap/$key
91 * $cid/all/$obj/attr/$name
92 * $cid/by_bitwise_hash/$hash/$bits/$obj - all objects with this (bitwise) hash (prefix)
104 FN_OBJECT_OMAP_HEADER
,
114 static int parse_fn(CephContext
* cct
, const char *path
, coll_t
*cid
,
115 ghobject_t
*oid
, string
*key
,
116 uint32_t *hash
, uint32_t *hash_bits
)
119 for (const char *p
= path
; *p
; ++p
) {
123 for (e
= p
+ 1; *e
&& *e
!= '/'; e
++) ;
130 ldout(cct
, 10) << __func__
<< " path " << path
<< " -> " << v
<< dendl
;
135 if (v
.front() == "type")
138 if (!cid
->parse(v
.front())) {
142 return FN_COLLECTION
;
145 if (v
.front() == "bitwise_hash_start")
146 return FN_HASH_START
;
147 if (v
.front() == "bitwise_hash_end")
149 if (v
.front() == "bitwise_hash_bits")
151 if (v
.front() == "pgmeta") {
153 if (cid
->is_pg(&pgid
)) {
154 *oid
= pgid
.make_pgmeta_oid();
162 if (v
.front() == "all") {
168 if (v
.front() == "by_bitwise_hash") {
172 unsigned long hv
, hm
;
173 int r
= sscanf(v
.front().c_str(), "%lx", &hv
);
176 int shift
= 32 - v
.front().length() * 4;
180 r
= sscanf(v
.front().c_str(), "%ld", &hm
);
183 if (hm
< 1 || hm
> 32)
186 *hash
= hv
<< shift
;//hobject_t::_reverse_bits(hv << shift);
196 string o
= v
.front();
197 if (!oid
->parse(o
)) {
206 if (v
.front() == "data")
207 return FN_OBJECT_DATA
;
208 if (v
.front() == "omap_header")
209 return FN_OBJECT_OMAP_HEADER
;
210 if (v
.front() == "omap") {
213 return FN_OBJECT_OMAP
;
217 return FN_OBJECT_OMAP_VAL
;
220 if (v
.front() == "attr") {
223 return FN_OBJECT_ATTR
;
227 return FN_OBJECT_ATTR_VAL
;
230 if (v
.front() == "bitwise_hash")
231 return FN_OBJECT_HASH
;
236 static int os_getattr(const char *path
, struct stat
*stbuf
237 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
238 , struct fuse_file_info
*fi
242 fuse_context
*fc
= fuse_get_context();
243 FuseStore
*fs
= static_cast<FuseStore
*>(fc
->private_data
);
244 ldout(fs
->store
->cct
, 10) << __func__
<< " " << path
<< dendl
;
248 uint32_t hash_value
, hash_bits
;
249 int t
= parse_fn(fs
->store
->cct
, path
, &cid
, &oid
, &key
, &hash_value
,
254 std::lock_guard
<std::mutex
> l(fs
->lock
);
259 stbuf
->st_mode
= S_IFREG
| 0700;
261 auto ch
= fs
->store
->open_collection(cid
);
268 case FN_OBJECT_OMAP_HEADER
:
269 case FN_OBJECT_OMAP_VAL
:
272 if (cid
.is_pg(&pgid
)) {
276 int bits
= fs
->store
->collection_bits(ch
);
277 if (bits
>= 0 && !oid
.match(bits
, pgid
.ps())) {
278 // sorry, not part of this PG
290 if (!fs
->store
->exists(ch
, oid
))
297 if (!fs
->store
->collection_exists(cid
))
301 stbuf
->st_mode
= S_IFDIR
| 0700;
305 stbuf
->st_size
= fs
->store
->get_type().length() + 1;
309 if (!fs
->store
->exists(ch
, oid
))
317 if (fs
->store
->collection_bits(ch
) < 0)
328 int bits
= fs
->store
->collection_bits(ch
);
332 snprintf(buf
, sizeof(buf
), "%d\n", bits
);
333 stbuf
->st_size
= strlen(buf
);
339 if (!fs
->store
->exists(ch
, oid
))
341 int r
= fs
->store
->stat(ch
, oid
, stbuf
);
347 case FN_OBJECT_OMAP_HEADER
:
349 if (!fs
->store
->exists(ch
, oid
))
352 fs
->store
->omap_get_header(ch
, oid
, &bl
);
353 stbuf
->st_size
= bl
.length();
357 case FN_OBJECT_OMAP_VAL
:
359 if (!fs
->store
->exists(ch
, oid
))
363 map
<string
,bufferlist
> v
;
364 fs
->store
->omap_get_values(ch
, oid
, k
, &v
);
368 stbuf
->st_size
= v
[key
].length();
372 case FN_OBJECT_ATTR_VAL
:
374 if (!fs
->store
->exists(ch
, oid
))
377 int r
= fs
->store
->getattr(ch
, oid
, key
.c_str(), v
);
382 stbuf
->st_size
= v
.length();
393 static int os_readdir(const char *path
,
395 fuse_fill_dir_t filler
,
397 struct fuse_file_info
*fi
398 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
399 , enum fuse_readdir_flags
403 fuse_context
*fc
= fuse_get_context();
404 FuseStore
*fs
= static_cast<FuseStore
*>(fc
->private_data
);
405 ldout(fs
->store
->cct
, 10) << __func__
<< " " << path
<< " offset " << offset
410 uint32_t hash_value
, hash_bits
;
411 int t
= parse_fn(fs
->store
->cct
, path
, &cid
, &oid
, &key
, &hash_value
,
416 std::lock_guard
<std::mutex
> l(fs
->lock
);
418 auto ch
= fs
->store
->open_collection(cid
);
420 // we can't shift 32 bits or else off_t will go negative
421 const int hash_shift
= 31;
426 filler_compat(filler
, buf
, "type", NULL
, 0);
428 fs
->store
->list_collections(cls
);
430 int r
= filler_compat(filler
, buf
, stringify(c
).c_str(), NULL
, 0);
442 filler_compat(filler
, buf
, "bitwise_hash_start", NULL
, 0);
443 if (fs
->store
->collection_bits(ch
) >= 0) {
444 filler_compat(filler
, buf
, "bitwise_hash_end", NULL
, 0);
445 filler_compat(filler
, buf
, "bitwise_hash_bits", NULL
, 0);
447 filler_compat(filler
, buf
, "all", NULL
, 0);
448 filler_compat(filler
, buf
, "by_bitwise_hash", NULL
, 0);
450 if (cid
.is_pg(&pgid
) &&
451 fs
->store
->exists(ch
, pgid
.make_pgmeta_oid())) {
452 filler_compat(filler
, buf
, "pgmeta", NULL
, 0);
459 filler_compat(filler
, buf
, "bitwise_hash", NULL
, 0);
460 filler_compat(filler
, buf
, "data", NULL
, 0);
461 filler_compat(filler
, buf
, "omap", NULL
, 0);
462 filler_compat(filler
, buf
, "attr", NULL
, 0);
463 filler_compat(filler
, buf
, "omap_header", NULL
, 0);
470 uint32_t bitwise_hash
= (offset
>> hash_shift
) & 0xffffffff;
471 uint32_t hashoff
= offset
- (bitwise_hash
<< hash_shift
);
473 ghobject_t next
= cid
.get_min_hobj();
476 next
.hobj
.set_hash(hobject_t::_reverse_bits(bitwise_hash
));
477 } else if (t
== FN_HASH_VAL
) {
478 next
.hobj
.set_hash(hobject_t::_reverse_bits(hash_value
));
481 if (t
== FN_HASH_VAL
) {
483 uint64_t rev_end
= (hash_value
| (0xffffffff >> hash_bits
)) + 1;
484 if (rev_end
>= 0x100000000)
485 last
= ghobject_t::get_max();
487 last
.hobj
.set_hash(hobject_t::_reverse_bits(rev_end
));
489 last
= ghobject_t::get_max();
491 ldout(fs
->store
->cct
, 10) << __func__
<< std::hex
492 << " offset " << offset
<< " hash "
493 << hobject_t::_reverse_bits(hash_value
)
496 << " first " << next
<< " last " << last
499 vector
<ghobject_t
> ls
;
500 int r
= fs
->store
->collection_list(
501 ch
, next
, last
, 1000, &ls
, &next
);
509 uint32_t cur_bitwise_hash
= p
.hobj
.get_bitwise_key_u32();
510 if (cur_bitwise_hash
!= bitwise_hash
) {
511 bitwise_hash
= cur_bitwise_hash
;
515 uint64_t cur_off
= ((uint64_t)bitwise_hash
<< hash_shift
) |
517 string s
= stringify(p
);
518 r
= filler_compat(filler
, buf
, s
.c_str(), NULL
, cur_off
);
524 if (next
== ghobject_t::get_max() || next
== last
)
533 fs
->store
->omap_get_keys(ch
, oid
, &keys
);
534 unsigned skip
= offset
;
535 for (auto k
: keys
) {
541 int r
= filler_compat(filler
, buf
, k
.c_str(), NULL
, offset
);
550 map
<string
,bufferptr
> aset
;
551 fs
->store
->getattrs(ch
, oid
, aset
);
552 unsigned skip
= offset
;
553 for (auto a
: aset
) {
559 int r
= filler_compat(filler
, buf
, a
.first
.c_str(), NULL
, offset
);
569 static int os_open(const char *path
, struct fuse_file_info
*fi
)
571 fuse_context
*fc
= fuse_get_context();
572 FuseStore
*fs
= static_cast<FuseStore
*>(fc
->private_data
);
573 ldout(fs
->store
->cct
, 10) << __func__
<< " " << path
<< dendl
;
577 uint32_t hash_value
, hash_bits
;
578 int t
= parse_fn(fs
->store
->cct
, path
, &cid
, &oid
, &key
, &hash_value
,
583 std::lock_guard
<std::mutex
> l(fs
->lock
);
585 auto ch
= fs
->store
->open_collection(cid
);
590 pbl
= new bufferlist
;
591 pbl
->append(fs
->store
->get_type());
597 pbl
= new bufferlist
;
599 if (cid
.is_pg(&pgid
)) {
601 h
= hobject_t::_reverse_bits(pgid
.ps());
603 snprintf(buf
, sizeof(buf
), "%08lx\n", h
);
606 pbl
->append("00000000\n");
618 if (cid
.is_pg(&pgid
)) {
619 int hash_bits
= fs
->store
->collection_bits(ch
);
620 if (hash_bits
>= 0) {
621 uint64_t rev_start
= hobject_t::_reverse_bits(pgid
.ps());
622 uint64_t rev_end
= (rev_start
| (0xffffffff >> hash_bits
));
631 snprintf(buf
, sizeof(buf
), "%08lx\n", h
);
632 pbl
= new bufferlist
;
642 int r
= fs
->store
->collection_bits(ch
);
646 snprintf(buf
, sizeof(buf
), "%d\n", r
);
647 pbl
= new bufferlist
;
654 pbl
= new bufferlist
;
656 snprintf(buf
, sizeof(buf
), "%08x\n",
657 (unsigned)oid
.hobj
.get_bitwise_key_u32());
664 int r
= fs
->open_file(
666 [&](bufferlist
*pbl
) {
667 return fs
->store
->read(ch
, oid
, 0, 0, *pbl
);
675 case FN_OBJECT_ATTR_VAL
:
677 int r
= fs
->open_file(
679 [&](bufferlist
*pbl
) {
681 int r
= fs
->store
->getattr(ch
, oid
, key
.c_str(), bp
);
692 case FN_OBJECT_OMAP_VAL
:
694 int r
= fs
->open_file(
696 [&](bufferlist
*pbl
) {
699 map
<string
,bufferlist
> v
;
700 int r
= fs
->store
->omap_get_values(ch
, oid
, k
, &v
);
711 case FN_OBJECT_OMAP_HEADER
:
713 int r
= fs
->open_file(
715 [&](bufferlist
*pbl
) {
716 return fs
->store
->omap_get_header(ch
, oid
, pbl
);
725 FuseStore::OpenFile
*o
= new FuseStore::OpenFile
;
727 fi
->fh
= reinterpret_cast<uint64_t>(o
);
732 static int os_mkdir(const char *path
, mode_t mode
)
734 fuse_context
*fc
= fuse_get_context();
735 FuseStore
*fs
= static_cast<FuseStore
*>(fc
->private_data
);
736 ldout(fs
->store
->cct
, 10) << __func__
<< " " << path
<< dendl
;
740 uint32_t hash_value
, hash_bits
;
741 int f
= parse_fn(fs
->store
->cct
, path
, &cid
, &oid
, &key
, &hash_value
,
746 std::lock_guard
<std::mutex
> l(fs
->lock
);
748 ObjectStore::CollectionHandle ch
;
750 ObjectStore::Transaction t
;
754 ch
= fs
->store
->open_collection(cid
);
759 if (cid
.is_pg(&pgid
)) {
760 int bits
= fs
->store
->collection_bits(ch
);
761 if (bits
>= 0 && !oid
.match(bits
, pgid
.ps())) {
762 // sorry, not part of this PG
767 ch
= fs
->store
->open_collection(cid
);
773 // use the mode for the bit count. e.g., mkdir --mode=0003
774 // mnt/0.7_head will create 0.7 with bits = 3.
781 t
.create_collection(cid
, mode
);
782 ch
= fs
->store
->create_new_collection(cid
);
790 fs
->store
->queue_transaction(ch
, std::move(t
));
796 static int os_chmod(const char *path
, mode_t mode
797 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
798 , struct fuse_file_info
*fi
802 fuse_context
*fc
= fuse_get_context();
803 FuseStore
*fs
= static_cast<FuseStore
*>(fc
->private_data
);
804 ldout(fs
->store
->cct
, 10) << __func__
<< " " << path
<< dendl
;
808 static int os_create(const char *path
, mode_t mode
, struct fuse_file_info
*fi
)
810 fuse_context
*fc
= fuse_get_context();
811 FuseStore
*fs
= static_cast<FuseStore
*>(fc
->private_data
);
812 ldout(fs
->store
->cct
, 10) << __func__
<< " " << path
<< dendl
;
816 uint32_t hash_value
, hash_bits
;
817 int f
= parse_fn(fs
->store
->cct
, path
, &cid
, &oid
, &key
, &hash_value
,
822 std::lock_guard
<std::mutex
> l(fs
->lock
);
824 ObjectStore::CollectionHandle ch
= fs
->store
->open_collection(cid
);
826 ObjectStore::Transaction t
;
831 pbl
= new bufferlist
;
832 fs
->store
->read(ch
, oid
, 0, 0, *pbl
);
836 case FN_OBJECT_ATTR_VAL
:
838 pbl
= new bufferlist
;
840 int r
= fs
->store
->getattr(ch
, oid
, key
.c_str(), bp
);
843 t
.setattr(cid
, oid
, key
.c_str(), empty
);
849 case FN_OBJECT_OMAP_VAL
:
851 pbl
= new bufferlist
;
854 map
<string
,bufferlist
> v
;
855 fs
->store
->omap_get_values(ch
, oid
, k
, &v
);
856 if (v
.count(key
) == 0) {
857 map
<string
,bufferlist
> aset
;
858 aset
[key
] = bufferlist();
859 t
.omap_setkeys(cid
, oid
, aset
);
868 fs
->store
->queue_transaction(ch
, std::move(t
));
872 FuseStore::OpenFile
*o
= new FuseStore::OpenFile
;
875 fi
->fh
= reinterpret_cast<uint64_t>(o
);
880 static int os_release(const char *path
, struct fuse_file_info
*fi
)
882 fuse_context
*fc
= fuse_get_context();
883 FuseStore
*fs
= static_cast<FuseStore
*>(fc
->private_data
);
884 ldout(fs
->store
->cct
, 10) << __func__
<< " " << path
<< dendl
;
885 std::lock_guard
<std::mutex
> l(fs
->lock
);
886 FuseStore::OpenFile
*o
= reinterpret_cast<FuseStore::OpenFile
*>(fi
->fh
);
888 ldout(fs
->store
->cct
, 10) << __func__
<< " closing last " << o
->path
<< dendl
;
889 fs
->open_files
.erase(o
->path
);
895 static int os_read(const char *path
, char *buf
, size_t size
, off_t offset
,
896 struct fuse_file_info
*fi
)
898 fuse_context
*fc
= fuse_get_context();
899 FuseStore
*fs
= static_cast<FuseStore
*>(fc
->private_data
);
900 ldout(fs
->store
->cct
, 10) << __func__
<< " " << path
<< " offset " << offset
901 << " size " << size
<< dendl
;
902 std::lock_guard
<std::mutex
> l(fs
->lock
);
903 FuseStore::OpenFile
*o
= reinterpret_cast<FuseStore::OpenFile
*>(fi
->fh
);
906 if (offset
>= o
->bl
.length())
908 if (offset
+ size
> o
->bl
.length())
909 size
= o
->bl
.length() - offset
;
911 r
.substr_of(o
->bl
, offset
, size
);
912 memcpy(buf
, r
.c_str(), r
.length());
916 static int os_write(const char *path
, const char *buf
, size_t size
,
917 off_t offset
, struct fuse_file_info
*fi
)
919 fuse_context
*fc
= fuse_get_context();
920 FuseStore
*fs
= static_cast<FuseStore
*>(fc
->private_data
);
921 ldout(fs
->store
->cct
, 10) << __func__
<< " " << path
<< " offset " << offset
922 << " size " << size
<< dendl
;
923 std::lock_guard
<std::mutex
> l(fs
->lock
);
924 FuseStore::OpenFile
*o
= reinterpret_cast<FuseStore::OpenFile
*>(fi
->fh
);
930 if (offset
> o
->bl
.length()) {
931 final
.substr_of(o
->bl
, 0, offset
);
933 final
.claim_append(o
->bl
);
934 size_t zlen
= offset
- final
.length();
935 final
.append_zero(zlen
);
938 final
.append(buf
, size
);
939 if (offset
+ size
< o
->bl
.length()) {
941 rest
.substr_of(o
->bl
, offset
+ size
, o
->bl
.length() - offset
- size
);
942 final
.claim_append(rest
);
949 int os_flush(const char *path
, struct fuse_file_info
*fi
)
951 fuse_context
*fc
= fuse_get_context();
952 FuseStore
*fs
= static_cast<FuseStore
*>(fc
->private_data
);
953 ldout(fs
->store
->cct
, 10) << __func__
<< " " << path
<< dendl
;
957 uint32_t hash_value
, hash_bits
;
958 int f
= parse_fn(fs
->store
->cct
, path
, &cid
, &oid
, &key
, &hash_value
,
963 std::lock_guard
<std::mutex
> l(fs
->lock
);
965 FuseStore::OpenFile
*o
= reinterpret_cast<FuseStore::OpenFile
*>(fi
->fh
);
971 ObjectStore::CollectionHandle ch
= fs
->store
->open_collection(cid
);
973 ObjectStore::Transaction t
;
977 t
.write(cid
, oid
, 0, o
->bl
.length(), o
->bl
);
980 case FN_OBJECT_ATTR_VAL
:
981 t
.setattr(cid
, oid
, key
.c_str(), o
->bl
);
984 case FN_OBJECT_OMAP_VAL
:
986 map
<string
,bufferlist
> aset
;
988 t
.omap_setkeys(cid
, oid
, aset
);
992 case FN_OBJECT_OMAP_HEADER
:
993 t
.omap_setheader(cid
, oid
, o
->bl
);
1000 fs
->store
->queue_transaction(ch
, std::move(t
));
1005 static int os_unlink(const char *path
)
1007 fuse_context
*fc
= fuse_get_context();
1008 FuseStore
*fs
= static_cast<FuseStore
*>(fc
->private_data
);
1009 ldout(fs
->store
->cct
, 10) << __func__
<< " " << path
<< dendl
;
1013 uint32_t hash_value
, hash_bits
;
1014 int f
= parse_fn(fs
->store
->cct
, path
, &cid
, &oid
, &key
, &hash_value
,
1019 std::lock_guard
<std::mutex
> l(fs
->lock
);
1021 ObjectStore::CollectionHandle ch
= fs
->store
->open_collection(cid
);
1022 ObjectStore::Transaction t
;
1025 case FN_OBJECT_OMAP_VAL
:
1027 t
.omap_rmkey(cid
, oid
, key
);
1031 case FN_OBJECT_ATTR_VAL
:
1032 t
.rmattr(cid
, oid
, key
.c_str());
1035 case FN_OBJECT_OMAP_HEADER
:
1038 t
.omap_setheader(cid
, oid
, empty
);
1049 int r
= fs
->store
->collection_empty(ch
, &empty
);
1054 t
.remove_collection(cid
);
1058 case FN_OBJECT_DATA
:
1059 t
.truncate(cid
, oid
, 0);
1066 fs
->store
->queue_transaction(ch
, std::move(t
));
1071 static int os_truncate(const char *path
, off_t size
1072 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
1073 , struct fuse_file_info
*fi
1077 fuse_context
*fc
= fuse_get_context();
1078 FuseStore
*fs
= static_cast<FuseStore
*>(fc
->private_data
);
1079 ldout(fs
->store
->cct
, 10) << __func__
<< " " << path
<< " size " << size
<< dendl
;
1083 uint32_t hash_value
, hash_bits
;
1084 int f
= parse_fn(fs
->store
->cct
, path
, &cid
, &oid
, &key
, &hash_value
,
1089 if (f
== FN_OBJECT_OMAP_VAL
||
1090 f
== FN_OBJECT_ATTR_VAL
||
1091 f
== FN_OBJECT_OMAP_HEADER
) {
1096 if (f
!= FN_OBJECT_DATA
)
1099 std::lock_guard
<std::mutex
> l(fs
->lock
);
1101 if (fs
->open_files
.count(path
)) {
1102 FuseStore::OpenFile
*o
= fs
->open_files
[path
];
1103 if (o
->bl
.length() > size
) {
1105 t
.substr_of(o
->bl
, 0, size
);
1110 ObjectStore::CollectionHandle ch
= fs
->store
->open_collection(cid
);
1111 ObjectStore::Transaction t
;
1112 t
.truncate(cid
, oid
, size
);
1113 fs
->store
->queue_transaction(ch
, std::move(t
));
1117 static int os_statfs(const char *path
, struct statvfs
*stbuf
)
1119 fuse_context
*fc
= fuse_get_context();
1120 FuseStore
*fs
= static_cast<FuseStore
*>(fc
->private_data
);
1121 ldout(fs
->store
->cct
, 10) << __func__
<< " " << path
<< dendl
;
1122 std::lock_guard
<std::mutex
> l(fs
->lock
);
1124 struct store_statfs_t s
;
1125 int r
= fs
->store
->statfs(&s
);
1128 stbuf
->f_bsize
= 4096; // LIES!
1129 stbuf
->f_blocks
= s
.total
/ 4096;
1130 stbuf
->f_bavail
= s
.available
/ 4096;
1131 stbuf
->f_bfree
= stbuf
->f_bavail
;
1133 ldout(fs
->store
->cct
, 10) << __func__
<< " " << path
<< ": "
1134 << stbuf
->f_bavail
<< "/" << stbuf
->f_blocks
<< dendl
;
1138 static struct fuse_operations fs_oper
= {
1139 getattr
: os_getattr
,
1141 #if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
1153 truncate
: os_truncate
,
1154 #if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
1162 release
: os_release
,
1169 readdir
: os_readdir
,
1178 int FuseStore::main()
1182 mount_point
.c_str(),
1187 auto fuse_debug
= store
->cct
->_conf
.get_val
<bool>("fuse_debug");
1190 return fuse_main(c
, (char**)v
, &fs_oper
, (void*)this);
1193 int FuseStore::start()
1195 dout(10) << __func__
<< dendl
;
1197 memset(&info
->args
, 0, sizeof(info
->args
));
1200 mount_point
.c_str(),
1205 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
1207 struct fuse_cmdline_opts opts
= {};
1209 auto fuse_debug
= store
->cct
->_conf
.get_val
<bool>("fuse_debug");
1212 fuse_args a
= FUSE_ARGS_INIT(c
, (char**)v
);
1214 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
1215 if (fuse_parse_cmdline(&info
->args
, &opts
) == -1) {
1217 if (fuse_parse_cmdline(&info
->args
, &info
->mountpoint
, NULL
, NULL
) == -1) {
1219 derr
<< __func__
<< " failed to parse args" << dendl
;
1223 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
1224 info
->mountpoint
= opts
.mountpoint
;
1225 info
->f
= fuse_new(&info
->args
, &fs_oper
, sizeof(fs_oper
), (void*)this);
1227 derr
<< __func__
<< " fuse_new failed" << dendl
;
1231 rc
= fuse_mount(info
->f
, info
->mountpoint
);
1233 derr
<< __func__
<< " fuse_mount failed" << dendl
;
1237 info
->ch
= fuse_mount(info
->mountpoint
, &info
->args
);
1239 derr
<< __func__
<< " fuse_mount failed" << dendl
;
1243 info
->f
= fuse_new(info
->ch
, &info
->args
, &fs_oper
, sizeof(fs_oper
),
1246 fuse_unmount(info
->mountpoint
, info
->ch
);
1247 derr
<< __func__
<< " fuse_new failed" << dendl
;
1252 fuse_thread
.create("fusestore");
1253 dout(10) << __func__
<< " done" << dendl
;
1257 int FuseStore::loop()
1259 dout(10) << __func__
<< " enter" << dendl
;
1260 int r
= fuse_loop(info
->f
);
1262 derr
<< __func__
<< " got " << cpp_strerror(r
) << dendl
;
1263 dout(10) << __func__
<< " exit" << dendl
;
1267 int FuseStore::stop()
1269 dout(10) << __func__
<< " enter" << dendl
;
1270 #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
1271 fuse_unmount(info
->f
);
1273 fuse_unmount(info
->mountpoint
, info
->ch
);
1276 fuse_destroy(info
->f
);
1277 dout(10) << __func__
<< " exit" << dendl
;