]> git.sesse.net Git - bcachefs-tools-debian/blob - cmd_fusemount.c
Add fuse symlink and readlink support.
[bcachefs-tools-debian] / cmd_fusemount.c
1 #include <errno.h>
2 #include <float.h>
3 #include <getopt.h>
4 #include <stdio.h>
5 #include <sys/statvfs.h>
6
7 #include <fuse_lowlevel.h>
8
9 #include "cmds.h"
10 #include "libbcachefs.h"
11 #include "tools-util.h"
12
13 #include "libbcachefs/bcachefs.h"
14 #include "libbcachefs/alloc_foreground.h"
15 #include "libbcachefs/btree_iter.h"
16 #include "libbcachefs/buckets.h"
17 #include "libbcachefs/dirent.h"
18 #include "libbcachefs/error.h"
19 #include "libbcachefs/fs-common.h"
20 #include "libbcachefs/inode.h"
21 #include "libbcachefs/io.h"
22 #include "libbcachefs/opts.h"
23 #include "libbcachefs/super.h"
24
25 /* mode_to_type(): */
26 #include "libbcachefs/fs.h"
27
28 #include <linux/dcache.h>
29
30 /* XXX cut and pasted from fsck.c */
31 #define QSTR(n) { { { .len = strlen(n) } }, .name = n }
32
33 static inline u64 map_root_ino(u64 ino)
34 {
35         return ino == 1 ? 4096 : ino;
36 }
37
38 static inline u64 unmap_root_ino(u64 ino)
39 {
40         return ino == 4096 ? 1 : ino;
41 }
42
43 static struct stat inode_to_stat(struct bch_fs *c,
44                                  struct bch_inode_unpacked *bi)
45 {
46         return (struct stat) {
47                 .st_ino         = bi->bi_inum,
48                 .st_size        = bi->bi_size,
49                 .st_mode        = bi->bi_mode,
50                 .st_uid         = bi->bi_uid,
51                 .st_gid         = bi->bi_gid,
52                 .st_nlink       = bch2_inode_nlink_get(bi),
53                 .st_rdev        = bi->bi_dev,
54                 .st_blksize     = block_bytes(c),
55                 .st_blocks      = bi->bi_sectors,
56                 .st_atim        = bch2_time_to_timespec(c, bi->bi_atime),
57                 .st_mtim        = bch2_time_to_timespec(c, bi->bi_mtime),
58                 .st_ctim        = bch2_time_to_timespec(c, bi->bi_ctime),
59         };
60 }
61
62 static struct fuse_entry_param inode_to_entry(struct bch_fs *c,
63                                               struct bch_inode_unpacked *bi)
64 {
65         return (struct fuse_entry_param) {
66                 .ino            = bi->bi_inum,
67                 .generation     = bi->bi_generation,
68                 .attr           = inode_to_stat(c, bi),
69                 .attr_timeout   = DBL_MAX,
70                 .entry_timeout  = DBL_MAX,
71         };
72 }
73
74 static void bcachefs_fuse_init(void *arg, struct fuse_conn_info *conn)
75 {
76         if (conn->capable & FUSE_CAP_WRITEBACK_CACHE) {
77                 fuse_log(FUSE_LOG_DEBUG, "fuse_init: activating writeback\n");
78                 conn->want |= FUSE_CAP_WRITEBACK_CACHE;
79         } else
80                 fuse_log(FUSE_LOG_DEBUG, "fuse_init: writeback not capable\n");
81
82         //conn->want |= FUSE_CAP_POSIX_ACL;
83 }
84
85 static void bcachefs_fuse_destroy(void *arg)
86 {
87         struct bch_fs *c = arg;
88
89         bch2_fs_stop(c);
90 }
91
92 static void bcachefs_fuse_lookup(fuse_req_t req, fuse_ino_t dir,
93                                  const char *name)
94 {
95         struct bch_fs *c = fuse_req_userdata(req);
96         struct bch_inode_unpacked bi;
97         struct qstr qstr = QSTR(name);
98         u64 inum;
99         int ret;
100
101         dir = map_root_ino(dir);
102
103         ret = bch2_inode_find_by_inum(c, dir, &bi);
104         if (ret) {
105                 fuse_reply_err(req, -ret);
106                 return;
107         }
108
109         struct bch_hash_info hash_info = bch2_hash_info_init(c, &bi);
110
111         inum = bch2_dirent_lookup(c, dir, &hash_info, &qstr);
112         if (!inum) {
113                 ret = -ENOENT;
114                 goto err;
115         }
116
117         ret = bch2_inode_find_by_inum(c, inum, &bi);
118         if (ret)
119                 goto err;
120
121         bi.bi_inum = unmap_root_ino(bi.bi_inum);
122
123         struct fuse_entry_param e = inode_to_entry(c, &bi);
124         fuse_reply_entry(req, &e);
125         return;
126 err:
127         fuse_reply_err(req, -ret);
128 }
129
130 static void bcachefs_fuse_getattr(fuse_req_t req, fuse_ino_t inum,
131                                   struct fuse_file_info *fi)
132 {
133         struct bch_fs *c = fuse_req_userdata(req);
134         struct bch_inode_unpacked bi;
135         struct stat attr;
136         int ret;
137
138         inum = map_root_ino(inum);
139
140         ret = bch2_inode_find_by_inum(c, inum, &bi);
141         if (ret) {
142                 fuse_reply_err(req, -ret);
143                 return;
144         }
145
146         bi.bi_inum = unmap_root_ino(bi.bi_inum);
147
148         attr = inode_to_stat(c, &bi);
149         fuse_reply_attr(req, &attr, DBL_MAX);
150 }
151
152 static void bcachefs_fuse_setattr(fuse_req_t req, fuse_ino_t inum,
153                                   struct stat *attr, int to_set,
154                                   struct fuse_file_info *fi)
155 {
156         struct bch_fs *c = fuse_req_userdata(req);
157         struct bch_inode_unpacked inode_u;
158         struct btree_trans trans;
159         struct btree_iter *iter;
160         u64 now;
161         int ret;
162
163         inum = map_root_ino(inum);
164
165         bch2_trans_init(&trans, c, 0, 0);
166 retry:
167         bch2_trans_begin(&trans);
168         now = bch2_current_time(c);
169
170         iter = bch2_inode_peek(&trans, &inode_u, inum, BTREE_ITER_INTENT);
171         ret = PTR_ERR_OR_ZERO(iter);
172         if (ret)
173                 goto err;
174
175         if (to_set & FUSE_SET_ATTR_MODE)
176                 inode_u.bi_mode = attr->st_mode;
177         if (to_set & FUSE_SET_ATTR_UID)
178                 inode_u.bi_uid  = attr->st_uid;
179         if (to_set & FUSE_SET_ATTR_GID)
180                 inode_u.bi_gid  = attr->st_gid;
181         if (to_set & FUSE_SET_ATTR_SIZE)
182                 inode_u.bi_size = attr->st_size;
183         if (to_set & FUSE_SET_ATTR_ATIME)
184                 inode_u.bi_atime = timespec_to_bch2_time(c, attr->st_atim);
185         if (to_set & FUSE_SET_ATTR_MTIME)
186                 inode_u.bi_mtime = timespec_to_bch2_time(c, attr->st_mtim);
187         if (to_set & FUSE_SET_ATTR_ATIME_NOW)
188                 inode_u.bi_atime = now;
189         if (to_set & FUSE_SET_ATTR_MTIME_NOW)
190                 inode_u.bi_mtime = now;
191         /* TODO: CTIME? */
192
193         ret   = bch2_inode_write(&trans, iter, &inode_u) ?:
194                 bch2_trans_commit(&trans, NULL, NULL,
195                                   BTREE_INSERT_ATOMIC|
196                                   BTREE_INSERT_NOFAIL);
197 err:
198         if (ret == -EINTR)
199                 goto retry;
200
201         bch2_trans_exit(&trans);
202
203         if (!ret) {
204                 *attr = inode_to_stat(c, &inode_u);
205                 fuse_reply_attr(req, attr, DBL_MAX);
206         } else {
207                 fuse_reply_err(req, -ret);
208         }
209 }
210
211 static int do_create(struct bch_fs *c, u64 dir,
212                      const char *name, mode_t mode, dev_t rdev,
213                      struct bch_inode_unpacked *new_inode)
214 {
215         struct qstr qstr = QSTR(name);
216         struct bch_inode_unpacked dir_u;
217
218         dir = map_root_ino(dir);
219
220         bch2_inode_init_early(c, new_inode);
221
222         return bch2_trans_do(c, NULL, BTREE_INSERT_ATOMIC,
223                         bch2_create_trans(&trans,
224                                 dir, &dir_u,
225                                 new_inode, &qstr,
226                                 0, 0, mode, rdev, NULL, NULL));
227 }
228
229 static void bcachefs_fuse_mknod(fuse_req_t req, fuse_ino_t dir,
230                                 const char *name, mode_t mode,
231                                 dev_t rdev)
232 {
233         struct bch_fs *c = fuse_req_userdata(req);
234         struct bch_inode_unpacked new_inode;
235         int ret;
236
237         ret = do_create(c, dir, name, mode, rdev, &new_inode);
238         if (ret)
239                 goto err;
240
241         struct fuse_entry_param e = inode_to_entry(c, &new_inode);
242         fuse_reply_entry(req, &e);
243         return;
244 err:
245         fuse_reply_err(req, -ret);
246 }
247
248 static void bcachefs_fuse_mkdir(fuse_req_t req, fuse_ino_t dir,
249                                 const char *name, mode_t mode)
250 {
251         bcachefs_fuse_mknod(req, dir, name, mode, 0);
252 }
253
254 static void bcachefs_fuse_unlink(fuse_req_t req, fuse_ino_t dir,
255                                  const char *name)
256 {
257         struct bch_fs *c = fuse_req_userdata(req);
258         struct bch_inode_unpacked dir_u, inode_u;
259         struct qstr qstr = QSTR(name);
260         int ret;
261
262         dir = map_root_ino(dir);
263
264         ret = bch2_trans_do(c, NULL, BTREE_INSERT_ATOMIC|BTREE_INSERT_NOFAIL,
265                             bch2_unlink_trans(&trans, dir, &dir_u,
266                                               &inode_u, &qstr));
267
268         fuse_reply_err(req, -ret);
269 }
270
271 static void bcachefs_fuse_rmdir(fuse_req_t req, fuse_ino_t dir,
272                                 const char *name)
273 {
274         dir = map_root_ino(dir);
275
276         bcachefs_fuse_unlink(req, dir, name);
277 }
278
279 static void bcachefs_fuse_rename(fuse_req_t req,
280                                  fuse_ino_t src_dir, const char *srcname,
281                                  fuse_ino_t dst_dir, const char *dstname,
282                                  unsigned flags)
283 {
284         struct bch_fs *c = fuse_req_userdata(req);
285         struct bch_inode_unpacked dst_dir_u, src_dir_u;
286         struct bch_inode_unpacked src_inode_u, dst_inode_u;
287         struct qstr dst_name = QSTR(srcname);
288         struct qstr src_name = QSTR(dstname);
289         int ret;
290
291         src_dir = map_root_ino(src_dir);
292         dst_dir = map_root_ino(dst_dir);
293
294         /* XXX handle overwrites */
295         ret = bch2_trans_do(c, NULL, BTREE_INSERT_ATOMIC,
296                 bch2_rename_trans(&trans,
297                                   src_dir, &src_dir_u,
298                                   dst_dir, &dst_dir_u,
299                                   &src_inode_u, &dst_inode_u,
300                                   &src_name, &dst_name,
301                                   BCH_RENAME));
302
303         fuse_reply_err(req, -ret);
304 }
305
306 static void bcachefs_fuse_link(fuse_req_t req, fuse_ino_t inum,
307                                fuse_ino_t newparent, const char *newname)
308 {
309         struct bch_fs *c = fuse_req_userdata(req);
310         struct bch_inode_unpacked inode_u;
311         struct qstr qstr = QSTR(newname);
312         int ret;
313
314         newparent = map_root_ino(newparent);
315
316         ret = bch2_trans_do(c, NULL, BTREE_INSERT_ATOMIC,
317                             bch2_link_trans(&trans, newparent,
318                                             inum, &inode_u, &qstr));
319
320         if (!ret) {
321                 struct fuse_entry_param e = inode_to_entry(c, &inode_u);
322                 fuse_reply_entry(req, &e);
323         } else {
324                 fuse_reply_err(req, -ret);
325         }
326 }
327
328 static void bcachefs_fuse_open(fuse_req_t req, fuse_ino_t inum,
329                                struct fuse_file_info *fi)
330 {
331         fi->direct_io           = false;
332         fi->keep_cache          = true;
333         fi->cache_readdir       = true;
334
335         fuse_reply_open(req, fi);
336 }
337
338 static void userbio_init(struct bio *bio, struct bio_vec *bv,
339                          void *buf, size_t size)
340 {
341         bio_init(bio, bv, 1);
342         bio->bi_iter.bi_size    = size;
343         bv->bv_page             = buf;
344         bv->bv_len              = size;
345         bv->bv_offset           = 0;
346 }
347
348 static int get_inode_io_opts(struct bch_fs *c, u64 inum,
349                              struct bch_io_opts *opts)
350 {
351         struct bch_inode_unpacked inode;
352         if (bch2_inode_find_by_inum(c, inum, &inode))
353                 return -EINVAL;
354
355         *opts = bch2_opts_to_inode_opts(c->opts);
356         bch2_io_opts_apply(opts, bch2_inode_opts_get(&inode));
357         return 0;
358 }
359
360 static void bcachefs_fuse_read_endio(struct bio *bio)
361 {
362         closure_put(bio->bi_private);
363 }
364
365 struct fuse_align_io {
366         off_t           start;
367         size_t          pad_start;
368         off_t           end;
369         size_t          pad_end;
370         size_t          size;
371 };
372
373 /* Handle unaligned start and end */
374 /* TODO: align to block_bytes, sector size, or page size? */
375 static void align_io(struct fuse_align_io *align, const struct bch_fs *c,
376                      size_t size, off_t offset)
377 {
378         BUG_ON(offset < 0);
379
380         align->start = round_down(offset, block_bytes(c));
381         align->pad_start = offset - align->start;
382
383         off_t end = offset + size;
384         align->end = round_up(end, block_bytes(c));
385         align->pad_end = align->end - end;
386
387         align->size = align->end - align->start;
388 }
389
390 /*
391  * Given an aligned number of bytes transferred, figure out how many unaligned
392  * bytes were transferred.
393  */
394 static size_t align_fix_up_bytes(const struct fuse_align_io *align,
395                                  size_t align_bytes)
396 {
397         size_t bytes = 0;
398
399         if (align_bytes > align->pad_start) {
400                 bytes = align_bytes - align->pad_start;
401                 bytes = bytes > align->pad_end ? bytes - align->pad_end : 0;
402         }
403
404         return bytes;
405 }
406
407 /*
408  * Read aligned data.
409  */
410 static int read_aligned(struct bch_fs *c, fuse_ino_t inum, size_t aligned_size,
411                         off_t aligned_offset, void *buf)
412 {
413         BUG_ON(aligned_size & (block_bytes(c) - 1));
414         BUG_ON(aligned_offset & (block_bytes(c) - 1));
415
416         struct bch_io_opts io_opts;
417         if (get_inode_io_opts(c, inum, &io_opts))
418                 return -ENOENT;
419
420         struct bch_read_bio rbio;
421         struct bio_vec bv;
422         userbio_init(&rbio.bio, &bv, buf, aligned_size);
423         bio_set_op_attrs(&rbio.bio, REQ_OP_READ, REQ_SYNC);
424         rbio.bio.bi_iter.bi_sector      = aligned_offset >> 9;
425
426         struct closure cl;
427         closure_init_stack(&cl);
428
429         closure_get(&cl);
430         rbio.bio.bi_end_io              = bcachefs_fuse_read_endio;
431         rbio.bio.bi_private             = &cl;
432
433         bch2_read(c, rbio_init(&rbio.bio, io_opts), inum);
434
435         closure_sync(&cl);
436
437         return -blk_status_to_errno(rbio.bio.bi_status);
438 }
439
440 static void bcachefs_fuse_read(fuse_req_t req, fuse_ino_t inum,
441                                size_t size, off_t offset,
442                                struct fuse_file_info *fi)
443 {
444         struct bch_fs *c = fuse_req_userdata(req);
445         struct fuse_align_io align;
446
447         fuse_log(FUSE_LOG_DEBUG, "bcachefs_fuse_read(%llu, %zd, %lld)\n",
448                  inum, size, offset);
449
450         /* Check inode size. */
451         struct bch_inode_unpacked bi;
452         int ret = bch2_inode_find_by_inum(c, inum, &bi);
453         if (ret) {
454                 fuse_reply_err(req, -ret);
455                 return;
456         }
457
458         off_t end = min_t(u64, bi.bi_size, offset + size);
459         if (end <= offset) {
460                 fuse_reply_buf(req, NULL, 0);
461                 return;
462         }
463         size = end - offset;
464
465         align_io(&align, c, size, offset);
466
467         void *buf = aligned_alloc(PAGE_SIZE, align.size);
468         if (!buf) {
469                 fuse_reply_err(req, ENOMEM);
470                 return;
471         }
472
473         ret = read_aligned(c, inum, align.size, align.start, buf);
474
475         if (likely(!ret))
476                 fuse_reply_buf(req, buf + align.pad_start, size);
477         else
478                 fuse_reply_err(req, -ret);
479
480         free(buf);
481 }
482
483 static int write_set_inode(struct bch_fs *c, fuse_ino_t inum, off_t new_size)
484 {
485         struct btree_trans trans;
486         struct btree_iter *iter;
487         struct bch_inode_unpacked inode_u;
488         int ret = 0;
489         u64 now;
490
491         bch2_trans_init(&trans, c, 0, 0);
492 retry:
493         bch2_trans_begin(&trans);
494         now = bch2_current_time(c);
495
496         iter = bch2_inode_peek(&trans, &inode_u, inum, BTREE_ITER_INTENT);
497         ret = PTR_ERR_OR_ZERO(iter);
498         if (ret)
499                 goto err;
500
501         inode_u.bi_size = max_t(u64, inode_u.bi_size, new_size);
502         inode_u.bi_mtime = now;
503         inode_u.bi_ctime = now;
504
505         ret = bch2_inode_write(&trans, iter, &inode_u);
506         if (ret)
507                 goto err;
508
509         ret = bch2_trans_commit(&trans, NULL, NULL,
510                                 BTREE_INSERT_ATOMIC|BTREE_INSERT_NOFAIL);
511
512 err:
513         if (ret == -EINTR)
514                 goto retry;
515
516         bch2_trans_exit(&trans);
517         return ret;
518 }
519
520 static int write_aligned(struct bch_fs *c, fuse_ino_t inum,
521                          struct bch_io_opts io_opts, void *buf,
522                          size_t aligned_size, off_t aligned_offset,
523                          size_t *written_out)
524 {
525         struct bch_write_op     op = { 0 };
526         struct bio_vec          bv;
527         struct closure          cl;
528
529         BUG_ON(aligned_size & (block_bytes(c) - 1));
530         BUG_ON(aligned_offset & (block_bytes(c) - 1));
531
532         *written_out = 0;
533
534         closure_init_stack(&cl);
535
536         bch2_write_op_init(&op, c, io_opts); /* XXX reads from op?! */
537         op.write_point  = writepoint_hashed(0);
538         op.nr_replicas  = io_opts.data_replicas;
539         op.target       = io_opts.foreground_target;
540         op.pos          = POS(inum, aligned_offset >> 9);
541
542         userbio_init(&op.wbio.bio, &bv, buf, aligned_size);
543         bio_set_op_attrs(&op.wbio.bio, REQ_OP_WRITE, REQ_SYNC);
544
545         if (bch2_disk_reservation_get(c, &op.res, aligned_size >> 9,
546                                       op.nr_replicas, 0)) {
547                 /* XXX: use check_range_allocated like dio write path */
548                 return -ENOSPC;
549         }
550
551         closure_call(&op.cl, bch2_write, NULL, &cl);
552         closure_sync(&cl);
553
554         if (!op.error)
555                 *written_out = op.written << 9;
556
557         return op.error;
558 }
559
560 static void bcachefs_fuse_write(fuse_req_t req, fuse_ino_t inum,
561                                 const char *buf, size_t size,
562                                 off_t offset,
563                                 struct fuse_file_info *fi)
564 {
565         struct bch_fs *c        = fuse_req_userdata(req);
566         struct bch_io_opts      io_opts;
567         struct fuse_align_io    align;
568         size_t                  aligned_written;
569         int                     ret = 0;
570
571         fuse_log(FUSE_LOG_DEBUG, "bcachefs_fuse_write(%llu, %zd, %lld)\n",
572                  inum, size, offset);
573
574         align_io(&align, c, size, offset);
575
576         if (get_inode_io_opts(c, inum, &io_opts)) {
577                 ret = -ENOENT;
578                 goto err;
579         }
580
581         /* Realign the data and read in start and end, if needed */
582         void *aligned_buf = aligned_alloc(PAGE_SIZE, align.size);
583
584         /* Read partial start data. */
585         if (align.pad_start) {
586                 memset(aligned_buf, 0, block_bytes(c));
587
588                 ret = read_aligned(c, inum, block_bytes(c), align.start,
589                                    aligned_buf);
590                 if (ret)
591                         goto err;
592         }
593
594         /*
595          * Read partial end data. If the whole write fits in one block, the
596          * start data and the end data are the same so this isn't needed.
597          */
598         if (align.pad_end &&
599             !(align.pad_start && align.size == block_bytes(c))) {
600                 off_t partial_end_start = align.end - block_bytes(c);
601                 size_t buf_offset = align.size - block_bytes(c);
602
603                 memset(aligned_buf + buf_offset, 0, block_bytes(c));
604
605                 ret = read_aligned(c, inum, block_bytes(c), partial_end_start,
606                                    aligned_buf + buf_offset);
607                 if (ret)
608                         goto err;
609         }
610
611         /* Overlay what we want to write. */
612         memcpy(aligned_buf + align.pad_start, buf, size);
613
614         /* Actually write. */
615         ret = write_aligned(c, inum, io_opts, aligned_buf,
616                             align.size, align.start, &aligned_written);
617
618         /* Figure out how many unaligned bytes were written. */
619         size_t written = align_fix_up_bytes(&align, aligned_written);
620         BUG_ON(written > size);
621
622         fuse_log(FUSE_LOG_DEBUG, "bcachefs_fuse_write: wrote %zd bytes\n",
623                  written);
624
625         if (written > 0)
626                 ret = 0;
627
628         /*
629          * Update inode data.
630          * TODO: Integrate with bch2_extent_update()
631          */
632         if (!ret)
633                 ret = write_set_inode(c, inum, offset + written);
634
635         if (!ret) {
636                 BUG_ON(written == 0);
637                 fuse_reply_write(req, written);
638                 return;
639         }
640
641 err:
642         fuse_reply_err(req, -ret);
643 }
644
645 static void bcachefs_fuse_symlink(fuse_req_t req, const char *link,
646                                   fuse_ino_t dir, const char *name)
647 {
648         struct bch_fs *c = fuse_req_userdata(req);
649         struct bch_inode_unpacked new_inode;
650         size_t link_len = strlen(link);
651         int ret;
652
653         dir = map_root_ino(dir);
654
655         ret = do_create(c, dir, name, S_IFLNK|S_IRWXUGO, 0, &new_inode);
656         if (ret)
657                 goto err;
658
659         struct bch_io_opts io_opts;
660         ret = get_inode_io_opts(c, new_inode.bi_inum, &io_opts);
661         if (ret)
662                 goto err;
663
664         struct fuse_align_io align;
665         align_io(&align, c, link_len + 1, 0);
666
667         void *aligned_buf = aligned_alloc(PAGE_SIZE, align.size);
668         memset(aligned_buf, 0, align.size);
669         memcpy(aligned_buf, link, link_len); /* already terminated */
670
671         size_t aligned_written;
672         ret = write_aligned(c, new_inode.bi_inum, io_opts, aligned_buf,
673                             align.size, align.start, &aligned_written);
674         free(aligned_buf);
675
676         if (ret)
677                 goto err;
678
679         size_t written = align_fix_up_bytes(&align, aligned_written);
680         BUG_ON(written != link_len + 1); // TODO: handle short
681
682         ret = write_set_inode(c, new_inode.bi_inum, written);
683         if (ret)
684                 goto err;
685
686         new_inode.bi_size = written;
687
688         struct fuse_entry_param e = inode_to_entry(c, &new_inode);
689         fuse_reply_entry(req, &e);
690         return;
691
692 err:
693         fuse_reply_err(req, -ret);
694 }
695
696 static void bcachefs_fuse_readlink(fuse_req_t req, fuse_ino_t inum)
697 {
698         struct bch_fs *c = fuse_req_userdata(req);
699         char *buf = NULL;
700
701         struct bch_inode_unpacked bi;
702         int ret = bch2_inode_find_by_inum(c, inum, &bi);
703         if (ret)
704                 goto err;
705
706         struct fuse_align_io align;
707         align_io(&align, c, bi.bi_size, 0);
708
709         ret = -ENOMEM;
710         buf = aligned_alloc(PAGE_SIZE, align.size);
711         if (!buf)
712                 goto err;
713
714         ret = read_aligned(c, inum, align.size, align.start, buf);
715         if (ret)
716                 goto err;
717
718         BUG_ON(buf[align.size - 1] != 0);
719
720         fuse_reply_readlink(req, buf);
721
722 err:
723         if (ret)
724                 fuse_reply_err(req, -ret);
725
726         free(buf);
727 }
728
729 #if 0
730 /*
731  * FUSE flush is essentially the close() call, however it is not guaranteed
732  * that one flush happens per open/create.
733  *
734  * It doesn't have to do anything, and is mostly relevant for NFS-style
735  * filesystems where close has some relationship to caching.
736  */
737 static void bcachefs_fuse_flush(fuse_req_t req, fuse_ino_t inum,
738                                 struct fuse_file_info *fi)
739 {
740         struct bch_fs *c = fuse_req_userdata(req);
741 }
742
743 static void bcachefs_fuse_release(fuse_req_t req, fuse_ino_t inum,
744                                   struct fuse_file_info *fi)
745 {
746         struct bch_fs *c = fuse_req_userdata(req);
747 }
748
749 static void bcachefs_fuse_fsync(fuse_req_t req, fuse_ino_t inum, int datasync,
750                                 struct fuse_file_info *fi)
751 {
752         struct bch_fs *c = fuse_req_userdata(req);
753 }
754
755 static void bcachefs_fuse_opendir(fuse_req_t req, fuse_ino_t inum,
756                                   struct fuse_file_info *fi)
757 {
758         struct bch_fs *c = fuse_req_userdata(req);
759 }
760 #endif
761
762 struct fuse_dir_entry {
763         u64             ino;
764         unsigned        type;
765         char            name[0];
766 };
767
768 struct fuse_dir_context {
769         struct dir_context      ctx;
770         fuse_req_t              req;
771         char                    *buf;
772         size_t                  bufsize;
773
774         struct fuse_dir_entry   *prev;
775 };
776
777 static int fuse_send_dir_entry(struct fuse_dir_context *ctx, loff_t pos)
778 {
779         struct fuse_dir_entry *de = ctx->prev;
780         ctx->prev = NULL;
781
782         struct stat statbuf = {
783                 .st_ino         = unmap_root_ino(de->ino),
784                 .st_mode        = de->type << 12,
785         };
786
787         size_t len = fuse_add_direntry(ctx->req, ctx->buf, ctx->bufsize,
788                                        de->name, &statbuf, pos);
789
790         free(de);
791
792         if (len > ctx->bufsize)
793                 return -EINVAL;
794
795         ctx->buf        += len;
796         ctx->bufsize    -= len;
797
798         return 0;
799 }
800
801 static int fuse_filldir(struct dir_context *_ctx,
802                         const char *name, int namelen,
803                         loff_t pos, u64 ino, unsigned type)
804 {
805         struct fuse_dir_context *ctx =
806                 container_of(_ctx, struct fuse_dir_context, ctx);
807
808         fuse_log(FUSE_LOG_DEBUG, "fuse_filldir(ctx={.ctx={.pos=%llu}}, "
809                  "name=%s, namelen=%d, pos=%lld, dir=%llu, type=%u)\n",
810                  ctx->ctx.pos, name, namelen, pos, ino, type);
811
812         /*
813          * We have to emit directory entries after reading the next entry,
814          * because the previous entry contains a pointer to next.
815          */
816         if (ctx->prev) {
817                 int ret = fuse_send_dir_entry(ctx, pos);
818                 if (ret)
819                         return ret;
820         }
821
822         struct fuse_dir_entry *cur = malloc(sizeof *cur + namelen + 1);
823         cur->ino = ino;
824         cur->type = type;
825         memcpy(cur->name, name, namelen);
826         cur->name[namelen] = 0;
827
828         ctx->prev = cur;
829
830         return 0;
831 }
832
833 static bool handle_dots(struct fuse_dir_context *ctx, fuse_ino_t dir)
834 {
835         int ret = 0;
836
837         if (ctx->ctx.pos == 0) {
838                 ret = fuse_filldir(&ctx->ctx, ".", 1, ctx->ctx.pos,
839                                    unmap_root_ino(dir), DT_DIR);
840                 if (ret < 0)
841                         return false;
842                 ctx->ctx.pos = 1;
843         }
844
845         if (ctx->ctx.pos == 1) {
846                 ret = fuse_filldir(&ctx->ctx, "..", 2, ctx->ctx.pos,
847                                    /*TODO: parent*/ 1, DT_DIR);
848                 if (ret < 0)
849                         return false;
850                 ctx->ctx.pos = 2;
851         }
852
853         return true;
854 }
855
856 static void bcachefs_fuse_readdir(fuse_req_t req, fuse_ino_t dir,
857                                   size_t size, off_t off,
858                                   struct fuse_file_info *fi)
859 {
860         struct bch_fs *c = fuse_req_userdata(req);
861         struct bch_inode_unpacked bi;
862         char *buf = calloc(size, 1);
863         struct fuse_dir_context ctx = {
864                 .ctx.actor      = fuse_filldir,
865                 .ctx.pos        = off,
866                 .req            = req,
867                 .buf            = buf,
868                 .bufsize        = size,
869         };
870         int ret = 0;
871
872         fuse_log(FUSE_LOG_DEBUG, "bcachefs_fuse_readdir(dir=%llu, size=%zu, "
873                  "off=%lld)\n", dir, size, off);
874
875         dir = map_root_ino(dir);
876
877         ret = bch2_inode_find_by_inum(c, dir, &bi);
878         if (ret)
879                 goto reply;
880
881         if (!S_ISDIR(bi.bi_mode)) {
882                 ret = -ENOTDIR;
883                 goto reply;
884         }
885
886         if (!handle_dots(&ctx, dir))
887                 goto reply;
888
889         ret = bch2_readdir(c, dir, &ctx.ctx);
890
891 reply:
892         /*
893          * If we have something to send, the error above doesn't matter.
894          *
895          * Alternatively, if this send fails, but we previously sent something,
896          * then this is a success.
897          */
898         if (ctx.prev) {
899                 ret = fuse_send_dir_entry(&ctx, ctx.ctx.pos);
900                 if (ret && ctx.buf != buf)
901                         ret = 0;
902         }
903
904         if (!ret) {
905                 fuse_log(FUSE_LOG_DEBUG, "bcachefs_fuse_readdir reply %zd\n",
906                                         ctx.buf - buf);
907                 fuse_reply_buf(req, buf, ctx.buf - buf);
908         } else {
909                 fuse_reply_err(req, -ret);
910         }
911
912         free(buf);
913 }
914
915 #if 0
916 static void bcachefs_fuse_readdirplus(fuse_req_t req, fuse_ino_t dir,
917                                       size_t size, off_t off,
918                                       struct fuse_file_info *fi)
919 {
920
921 }
922
923 static void bcachefs_fuse_releasedir(fuse_req_t req, fuse_ino_t inum,
924                                      struct fuse_file_info *fi)
925 {
926         struct bch_fs *c = fuse_req_userdata(req);
927 }
928
929 static void bcachefs_fuse_fsyncdir(fuse_req_t req, fuse_ino_t inum, int datasync,
930                                    struct fuse_file_info *fi)
931 {
932         struct bch_fs *c = fuse_req_userdata(req);
933 }
934 #endif
935
936 static void bcachefs_fuse_statfs(fuse_req_t req, fuse_ino_t inum)
937 {
938         struct bch_fs *c = fuse_req_userdata(req);
939         struct bch_fs_usage_short usage = bch2_fs_usage_read_short(c);
940         unsigned shift = c->block_bits;
941         struct statvfs statbuf = {
942                 .f_bsize        = block_bytes(c),
943                 .f_frsize       = block_bytes(c),
944                 .f_blocks       = usage.capacity >> shift,
945                 .f_bfree        = (usage.capacity - usage.used) >> shift,
946                 //.f_bavail     = statbuf.f_bfree,
947                 .f_files        = usage.nr_inodes,
948                 .f_ffree        = U64_MAX,
949                 .f_namemax      = BCH_NAME_MAX,
950         };
951
952         fuse_reply_statfs(req, &statbuf);
953 }
954
955 #if 0
956 static void bcachefs_fuse_setxattr(fuse_req_t req, fuse_ino_t inum,
957                                    const char *name, const char *value,
958                                    size_t size, int flags)
959 {
960         struct bch_fs *c = fuse_req_userdata(req);
961 }
962
963 static void bcachefs_fuse_getxattr(fuse_req_t req, fuse_ino_t inum,
964                                    const char *name, size_t size)
965 {
966         struct bch_fs *c = fuse_req_userdata(req);
967
968         fuse_reply_xattr(req, );
969 }
970
971 static void bcachefs_fuse_listxattr(fuse_req_t req, fuse_ino_t inum, size_t size)
972 {
973         struct bch_fs *c = fuse_req_userdata(req);
974 }
975
976 static void bcachefs_fuse_removexattr(fuse_req_t req, fuse_ino_t inum,
977                                       const char *name)
978 {
979         struct bch_fs *c = fuse_req_userdata(req);
980 }
981 #endif
982
983 static void bcachefs_fuse_create(fuse_req_t req, fuse_ino_t dir,
984                                  const char *name, mode_t mode,
985                                  struct fuse_file_info *fi)
986 {
987         struct bch_fs *c = fuse_req_userdata(req);
988         struct bch_inode_unpacked new_inode;
989         int ret;
990
991         ret = do_create(c, dir, name, mode, 0, &new_inode);
992         if (ret)
993                 goto err;
994
995         struct fuse_entry_param e = inode_to_entry(c, &new_inode);
996         fuse_reply_create(req, &e, fi);
997         return;
998 err:
999         fuse_reply_err(req, -ret);
1000
1001 }
1002
1003 #if 0
1004 static void bcachefs_fuse_write_buf(fuse_req_t req, fuse_ino_t inum,
1005                                     struct fuse_bufvec *bufv, off_t off,
1006                                     struct fuse_file_info *fi)
1007 {
1008         struct bch_fs *c = fuse_req_userdata(req);
1009 }
1010
1011 static void bcachefs_fuse_fallocate(fuse_req_t req, fuse_ino_t inum, int mode,
1012                                     off_t offset, off_t length,
1013                                     struct fuse_file_info *fi)
1014 {
1015         struct bch_fs *c = fuse_req_userdata(req);
1016 }
1017 #endif
1018
1019 static const struct fuse_lowlevel_ops bcachefs_fuse_ops = {
1020         .init           = bcachefs_fuse_init,
1021         .destroy        = bcachefs_fuse_destroy,
1022         .lookup         = bcachefs_fuse_lookup,
1023         .getattr        = bcachefs_fuse_getattr,
1024         .setattr        = bcachefs_fuse_setattr,
1025         .readlink       = bcachefs_fuse_readlink,
1026         .mknod          = bcachefs_fuse_mknod,
1027         .mkdir          = bcachefs_fuse_mkdir,
1028         .unlink         = bcachefs_fuse_unlink,
1029         .rmdir          = bcachefs_fuse_rmdir,
1030         .symlink        = bcachefs_fuse_symlink,
1031         .rename         = bcachefs_fuse_rename,
1032         .link           = bcachefs_fuse_link,
1033         .open           = bcachefs_fuse_open,
1034         .read           = bcachefs_fuse_read,
1035         .write          = bcachefs_fuse_write,
1036         //.flush        = bcachefs_fuse_flush,
1037         //.release      = bcachefs_fuse_release,
1038         //.fsync        = bcachefs_fuse_fsync,
1039         //.opendir      = bcachefs_fuse_opendir,
1040         .readdir        = bcachefs_fuse_readdir,
1041         //.readdirplus  = bcachefs_fuse_readdirplus,
1042         //.releasedir   = bcachefs_fuse_releasedir,
1043         //.fsyncdir     = bcachefs_fuse_fsyncdir,
1044         .statfs         = bcachefs_fuse_statfs,
1045         //.setxattr     = bcachefs_fuse_setxattr,
1046         //.getxattr     = bcachefs_fuse_getxattr,
1047         //.listxattr    = bcachefs_fuse_listxattr,
1048         //.removexattr  = bcachefs_fuse_removexattr,
1049         .create         = bcachefs_fuse_create,
1050
1051         /* posix locks: */
1052 #if 0
1053         .getlk          = bcachefs_fuse_getlk,
1054         .setlk          = bcachefs_fuse_setlk,
1055 #endif
1056         //.write_buf    = bcachefs_fuse_write_buf,
1057         //.fallocate    = bcachefs_fuse_fallocate,
1058
1059 };
1060
1061 /*
1062  * Setup and command parsing.
1063  */
1064
1065 struct bf_context {
1066         char            *devices_str;
1067         char            **devices;
1068         int             nr_devices;
1069 };
1070
1071 static void bf_context_free(struct bf_context *ctx)
1072 {
1073         int i;
1074
1075         free(ctx->devices_str);
1076         for (i = 0; i < ctx->nr_devices; ++i)
1077                 free(ctx->devices[i]);
1078         free(ctx->devices);
1079 }
1080
1081 static struct fuse_opt bf_opts[] = {
1082         FUSE_OPT_END
1083 };
1084
1085 /*
1086  * Fuse option parsing helper -- returning 0 means we consumed the argument, 1
1087  * means we did not.
1088  */
1089 static int bf_opt_proc(void *data, const char *arg, int key,
1090     struct fuse_args *outargs)
1091 {
1092         struct bf_context *ctx = data;
1093
1094         switch (key) {
1095         case FUSE_OPT_KEY_NONOPT:
1096                 /* Just extract the first non-option string. */
1097                 if (!ctx->devices_str) {
1098                         ctx->devices_str = strdup(arg);
1099                         return 0;
1100                 }
1101                 return 1;
1102         }
1103
1104         return 1;
1105 }
1106
1107 /*
1108  * dev1:dev2 -> [ dev1, dev2 ]
1109  * dev       -> [ dev ]
1110  */
1111 static void tokenize_devices(struct bf_context *ctx)
1112 {
1113         char *devices_str = strdup(ctx->devices_str);
1114         char *devices_tmp = devices_str;
1115         char **devices = NULL;
1116         int nr = 0;
1117         char *dev = NULL;
1118
1119         while ((dev = strsep(&devices_tmp, ":"))) {
1120                 if (strlen(dev) > 0) {
1121                         devices = realloc(devices, (nr + 1) * sizeof *devices);
1122                         devices[nr] = strdup(dev);
1123                         nr++;
1124                 }
1125         }
1126
1127         if (!devices) {
1128                 devices = malloc(sizeof *devices);
1129                 devices[0] = strdup(ctx->devices_str);
1130                 nr = 1;
1131         }
1132
1133         ctx->devices = devices;
1134         ctx->nr_devices = nr;
1135
1136         free(devices_str);
1137 }
1138
1139 static void usage(char *argv[])
1140 {
1141         printf("Usage: %s fusemount [options] <dev>[:dev2:...] <mountpoint>\n",
1142                argv[0]);
1143         printf("\n");
1144 }
1145
1146 int cmd_fusemount(int argc, char *argv[])
1147 {
1148         struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
1149         struct bch_opts bch_opts = bch2_opts_empty();
1150         struct bf_context ctx = { 0 };
1151         struct bch_fs *c = NULL;
1152         int ret = 0, i;
1153
1154         /* Parse arguments. */
1155         if (fuse_opt_parse(&args, &ctx, bf_opts, bf_opt_proc) < 0)
1156                 die("fuse_opt_parse err: %m");
1157
1158         struct fuse_cmdline_opts fuse_opts;
1159         if (fuse_parse_cmdline(&args, &fuse_opts) < 0)
1160                 die("fuse_parse_cmdline err: %m");
1161
1162         if (fuse_opts.show_help) {
1163                 usage(argv);
1164                 fuse_cmdline_help();
1165                 fuse_lowlevel_help();
1166                 ret = 0;
1167                 goto out;
1168         }
1169         if (fuse_opts.show_version) {
1170                 /* TODO: Show bcachefs version. */
1171                 printf("FUSE library version %s\n", fuse_pkgversion());
1172                 fuse_lowlevel_version();
1173                 ret = 0;
1174                 goto out;
1175         }
1176         if (!fuse_opts.mountpoint) {
1177                 usage(argv);
1178                 printf("Please supply a mountpoint.\n");
1179                 ret = 1;
1180                 goto out;
1181         }
1182         if (!ctx.devices_str) {
1183                 usage(argv);
1184                 printf("Please specify a device or device1:device2:...\n");
1185                 ret = 1;
1186                 goto out;
1187         }
1188         tokenize_devices(&ctx);
1189
1190         /* Open bch */
1191         printf("Opening bcachefs filesystem on:\n");
1192         for (i = 0; i < ctx.nr_devices; ++i)
1193                 printf("\t%s\n", ctx.devices[i]);
1194
1195         c = bch2_fs_open(ctx.devices, ctx.nr_devices, bch_opts);
1196         if (IS_ERR(c))
1197                 die("error opening %s: %s", ctx.devices_str,
1198                     strerror(-PTR_ERR(c)));
1199
1200         /* Fuse */
1201         struct fuse_session *se =
1202                 fuse_session_new(&args, &bcachefs_fuse_ops,
1203                                  sizeof(bcachefs_fuse_ops), c);
1204         if (!se)
1205                 die("fuse_lowlevel_new err: %m");
1206
1207         if (fuse_set_signal_handlers(se) < 0)
1208                 die("fuse_set_signal_handlers err: %m");
1209
1210         if (fuse_session_mount(se, fuse_opts.mountpoint))
1211                 die("fuse_mount err: %m");
1212
1213         fuse_daemonize(fuse_opts.foreground);
1214
1215         ret = fuse_session_loop(se);
1216
1217         /* Cleanup */
1218         fuse_session_unmount(se);
1219         fuse_remove_signal_handlers(se);
1220         fuse_session_destroy(se);
1221
1222 out:
1223         free(fuse_opts.mountpoint);
1224         fuse_opt_free_args(&args);
1225         bf_context_free(&ctx);
1226
1227         return ret ? 1 : 0;
1228 }