1 /* $OpenBSD: fuse_device.c,v 1.15 2014/07/12 18:43:52 tedu Exp $ */ 2 /* 3 * Copyright (c) 2012-2013 Sylvestre Gallon <ccna.syl@gmail.com> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/fcntl.h> 21 #include <sys/ioctl.h> 22 #include <sys/malloc.h> 23 #include <sys/mount.h> 24 #include <sys/poll.h> 25 #include <sys/statvfs.h> 26 #include <sys/vnode.h> 27 #include <sys/fusebuf.h> 28 29 #include "fusefs_node.h" 30 #include "fusefs.h" 31 32 #ifdef FUSE_DEBUG 33 #define DPRINTF(fmt, arg...) printf("%s: " fmt, "fuse", ##arg) 34 #else 35 #define DPRINTF(fmt, arg...) 36 #endif 37 38 SIMPLEQ_HEAD(fusebuf_head, fusebuf); 39 40 struct fuse_d { 41 struct fusefs_mnt *fd_fmp; 42 int fd_unit; 43 44 /*fusebufs queues*/ 45 struct fusebuf_head fd_fbufs_in; 46 struct fusebuf_head fd_fbufs_wait; 47 48 /* kq fields */ 49 struct selinfo fd_rsel; 50 LIST_ENTRY(fuse_d) fd_list; 51 }; 52 53 int stat_fbufs_in = 0; 54 int stat_fbufs_wait = 0; 55 int stat_opened_fusedev = 0; 56 57 LIST_HEAD(, fuse_d) fuse_d_list; 58 struct fuse_d *fuse_create(int); 59 struct fuse_d *fuse_lookup(int); 60 void fuse_destroy(dev_t dev, struct fuse_d *fd); 61 62 void fuseattach(int); 63 int fuseopen(dev_t, int, int, struct proc *); 64 int fuseclose(dev_t, int, int, struct proc *); 65 int fuseioctl(dev_t, u_long, caddr_t, int, struct proc *); 66 int fuseread(dev_t, struct uio *, int); 67 int fusewrite(dev_t, struct uio *, int); 68 int fusepoll(dev_t, int, struct proc *); 69 int fusekqfilter(dev_t dev, struct knote *kn); 70 int filt_fuse_read(struct knote *, long); 71 void filt_fuse_rdetach(struct knote *); 72 73 const static struct filterops fuse_rd_filtops = { 74 1, 75 NULL, 76 filt_fuse_rdetach, 77 filt_fuse_read 78 }; 79 80 const static struct filterops fuse_seltrue_filtops = { 81 1, 82 NULL, 83 filt_fuse_rdetach, 84 filt_seltrue 85 }; 86 87 #ifdef FUSE_DEBUG 88 static void 89 fuse_dump_buff(char *buff, int len) 90 { 91 char text[17]; 92 int i; 93 94 bzero(text, 17); 95 for (i = 0; i < len; i++) { 96 if (i != 0 && (i % 16) == 0) { 97 printf(": %s\n", text); 98 bzero(text, 17); 99 } 100 101 printf("%.2x ", buff[i] & 0xff); 102 103 if (buff[i] > ' ' && buff[i] < '~') 104 text[i%16] = buff[i] & 0xff; 105 else 106 text[i%16] = '.'; 107 } 108 109 if ((i % 16) != 0) 110 while ((i % 16) != 0) { 111 printf(" "); 112 i++; 113 } 114 115 printf(": %s\n", text); 116 } 117 #endif 118 119 struct fuse_d * 120 fuse_lookup(int unit) 121 { 122 struct fuse_d *fd; 123 124 LIST_FOREACH(fd, &fuse_d_list, fd_list) 125 if (fd->fd_unit == unit) 126 return (fd); 127 return (NULL); 128 } 129 130 struct fuse_d * 131 fuse_create(int unit) 132 { 133 struct fuse_d *fd; 134 135 if ((fd = fuse_lookup(unit)) != NULL) 136 return (NULL); 137 138 fd = malloc(sizeof(*fd), M_DEVBUF, M_WAITOK | M_ZERO); 139 fd->fd_unit = unit; 140 SIMPLEQ_INIT(&fd->fd_fbufs_in); 141 SIMPLEQ_INIT(&fd->fd_fbufs_wait); 142 LIST_INSERT_HEAD(&fuse_d_list, fd, fd_list); 143 return (fd); 144 } 145 146 void 147 fuse_destroy(dev_t dev, struct fuse_d *fd) 148 { 149 LIST_REMOVE(fd, fd_list); 150 fuse_device_cleanup(dev, NULL); 151 free(fd, M_DEVBUF, 0); 152 } 153 154 /* 155 * if fbuf == NULL cleanup all msgs else remove fbuf from 156 * sc_fbufs_in and sc_fbufs_wait. 157 */ 158 void 159 fuse_device_cleanup(dev_t dev, struct fusebuf *fbuf) 160 { 161 struct fuse_d *fd; 162 struct fusebuf *f, *ftmp, *lprev; 163 164 fd = fuse_lookup(minor(dev)); 165 if (fd == NULL) 166 return; 167 168 /* clear FIFO IN*/ 169 lprev = NULL; 170 SIMPLEQ_FOREACH_SAFE(f, &fd->fd_fbufs_in, fb_next, ftmp) { 171 if (fbuf == f || fbuf == NULL) { 172 DPRINTF("cleanup unprocessed msg in sc_fbufs_in\n"); 173 if (lprev == NULL) 174 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_in, fb_next); 175 else 176 SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_in, lprev, 177 fb_next); 178 179 stat_fbufs_in--; 180 if (fbuf == NULL) 181 fb_delete(f); 182 else 183 break; 184 } 185 lprev = f; 186 } 187 188 /* clear FIFO WAIT*/ 189 lprev = NULL; 190 SIMPLEQ_FOREACH_SAFE(f, &fd->fd_fbufs_wait, fb_next, ftmp) { 191 if (fbuf == f || fbuf == NULL) { 192 DPRINTF("umount unprocessed msg in sc_fbufs_wait\n"); 193 if (lprev == NULL) 194 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_wait, 195 fb_next); 196 else 197 SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_wait, lprev, 198 fb_next); 199 200 stat_fbufs_wait--; 201 if (fbuf == NULL) 202 fb_delete(f); 203 else 204 break; 205 } 206 lprev = f; 207 } 208 } 209 210 void 211 fuse_device_queue_fbuf(dev_t dev, struct fusebuf *fbuf) 212 { 213 struct fuse_d *fd; 214 215 fd = fuse_lookup(minor(dev)); 216 if (fd == NULL) 217 return; 218 219 SIMPLEQ_INSERT_TAIL(&fd->fd_fbufs_in, fbuf, fb_next); 220 stat_fbufs_in++; 221 selwakeup(&fd->fd_rsel); 222 } 223 224 void 225 fuse_device_set_fmp(struct fusefs_mnt *fmp, int set) 226 { 227 struct fuse_d *fd; 228 229 fd = fuse_lookup(minor(fmp->dev)); 230 if (fd == NULL) 231 return; 232 233 fd->fd_fmp = set ? fmp : NULL; 234 } 235 236 void 237 fuseattach(int num) 238 { 239 LIST_INIT(&fuse_d_list); 240 } 241 242 int 243 fuseopen(dev_t dev, int flags, int fmt, struct proc * p) 244 { 245 struct fuse_d *fd; 246 247 if (flags & O_EXCL) 248 return (EBUSY); /* No exclusive opens */ 249 250 if ((fd = fuse_create(minor(dev))) == NULL) 251 return (EBUSY); 252 253 stat_opened_fusedev++; 254 return (0); 255 } 256 257 int 258 fuseclose(dev_t dev, int flags, int fmt, struct proc *p) 259 { 260 struct fuse_d *fd; 261 int error; 262 263 fd = fuse_lookup(minor(dev)); 264 if (fd == NULL) 265 return (EINVAL); 266 267 if (fd->fd_fmp) { 268 printf("fuse: device close without umount\n"); 269 fd->fd_fmp->sess_init = 0; 270 if ((vfs_busy(fd->fd_fmp->mp, VB_WRITE|VB_NOWAIT)) != 0) 271 goto end; 272 if ((error = dounmount(fd->fd_fmp->mp, MNT_FORCE, curproc, 273 NULL)) != 0) 274 printf("fuse: unmount failed with error %d\n", error); 275 fd->fd_fmp = NULL; 276 } 277 278 end: 279 fuse_destroy(dev, fd); 280 stat_opened_fusedev--; 281 return (0); 282 } 283 284 /* 285 * FIOCGETFBDAT Get fusebuf datas from kernel to user 286 * FIOCSETFBDAT Set fusebuf datas from user to kernel 287 */ 288 int 289 fuseioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) 290 { 291 struct fb_ioctl_xch *ioexch; 292 struct fusebuf *lastfbuf; 293 struct fusebuf *fbuf; 294 struct fuse_d *fd; 295 int error = 0; 296 297 fd = fuse_lookup(minor(dev)); 298 299 switch (cmd) { 300 case FIOCGETFBDAT: 301 ioexch = (struct fb_ioctl_xch *)addr; 302 303 /* Looking for uuid in fd_fbufs_in */ 304 SIMPLEQ_FOREACH(fbuf, &fd->fd_fbufs_in, fb_next) { 305 if (fbuf->fb_uuid == ioexch->fbxch_uuid) 306 break; 307 308 lastfbuf = fbuf; 309 } 310 if (fbuf == NULL) { 311 printf("fuse: Cannot find fusebuf\n"); 312 return (EINVAL); 313 } 314 315 /* Remove the fbuf from fd_fbufs_in */ 316 if (fbuf == SIMPLEQ_FIRST(&fd->fd_fbufs_in)) 317 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_in, fb_next); 318 else 319 SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_in, lastfbuf, 320 fb_next); 321 stat_fbufs_in--; 322 323 /* Do not handle fbufs with bad len */ 324 if (fbuf->fb_len != ioexch->fbxch_len) { 325 printf("fuse: Bad fusebuf len\n"); 326 return (EINVAL); 327 } 328 329 /* Update the userland fbuf */ 330 error = copyout(fbuf->fb_dat, ioexch->fbxch_data, 331 ioexch->fbxch_len); 332 if (error) { 333 printf("fuse: cannot copyout\n"); 334 return (error); 335 } 336 337 #ifdef FUSE_DEBUG 338 fuse_dump_buff(ioexch->fbxch_data, ioexch->fbxch_len); 339 #endif 340 341 /* Adding fbuf in fd_fbufs_wait */ 342 free(fbuf->fb_dat, M_FUSEFS, 0); 343 fbuf->fb_dat = NULL; 344 SIMPLEQ_INSERT_TAIL(&fd->fd_fbufs_wait, fbuf, fb_next); 345 stat_fbufs_wait++; 346 break; 347 348 case FIOCSETFBDAT: 349 DPRINTF("SET BUFFER\n"); 350 ioexch = (struct fb_ioctl_xch *)addr; 351 352 /* looking for uuid in fd_fbufs_wait */ 353 SIMPLEQ_FOREACH(fbuf, &fd->fd_fbufs_wait, fb_next) { 354 if (fbuf->fb_uuid == ioexch->fbxch_uuid) 355 break; 356 357 lastfbuf = fbuf; 358 } 359 if (fbuf == NULL) { 360 printf("fuse: Cannot find fusebuf\n"); 361 return (EINVAL); 362 } 363 364 /* Do not handle fbufs with bad len */ 365 if (fbuf->fb_len != ioexch->fbxch_len) { 366 printf("fuse: Bad fusebuf size\n"); 367 return (EINVAL); 368 } 369 370 /* fetching data from userland */ 371 fbuf->fb_dat = malloc(ioexch->fbxch_len, M_FUSEFS, 372 M_WAITOK | M_ZERO); 373 error = copyin(ioexch->fbxch_data, fbuf->fb_dat, 374 ioexch->fbxch_len); 375 if (error) { 376 printf("fuse: Cannot copyin\n"); 377 free(fbuf->fb_dat, M_FUSEFS, 0); 378 fbuf->fb_dat = NULL; 379 return (error); 380 } 381 382 #ifdef FUSE_DEBUG 383 fuse_dump_buff(fbuf->fb_dat, fbuf->fb_len); 384 #endif 385 386 /* Remove fbuf from fd_fbufs_wait */ 387 if (fbuf == SIMPLEQ_FIRST(&fd->fd_fbufs_wait)) 388 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_wait, fb_next); 389 else 390 SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_wait, lastfbuf, 391 fb_next); 392 stat_fbufs_wait--; 393 wakeup(fbuf); 394 break; 395 default: 396 error = EINVAL; 397 } 398 399 return (error); 400 } 401 402 int 403 fuseread(dev_t dev, struct uio *uio, int ioflag) 404 { 405 struct fuse_d *fd; 406 struct fusebuf *fbuf; 407 struct fb_hdr hdr; 408 void *tmpaddr; 409 int error = 0; 410 411 fd = fuse_lookup(minor(dev)); 412 if (fd == NULL) 413 return (ENXIO); 414 415 if (SIMPLEQ_EMPTY(&fd->fd_fbufs_in)) { 416 if (ioflag & O_NONBLOCK) 417 return (EAGAIN); 418 419 goto end; 420 } 421 fbuf = SIMPLEQ_FIRST(&fd->fd_fbufs_in); 422 423 /* We get the whole fusebuf or nothing */ 424 if (uio->uio_resid != FUSEBUFSIZE) 425 return (EINVAL); 426 427 /* Do not send kernel pointers */ 428 memcpy(&hdr.fh_next, &fbuf->fb_next, sizeof(fbuf->fb_next)); 429 bzero(&fbuf->fb_next, sizeof(fbuf->fb_next)); 430 tmpaddr = fbuf->fb_dat; 431 fbuf->fb_dat = NULL; 432 error = uiomove(fbuf, FUSEBUFSIZE, uio); 433 if (error) 434 goto end; 435 436 #ifdef FUSE_DEBUG 437 fuse_dump_buff((char *)fbuf, FUSEBUFSIZE); 438 #endif 439 /* Restore kernel pointers */ 440 memcpy(&fbuf->fb_next, &hdr.fh_next, sizeof(fbuf->fb_next)); 441 fbuf->fb_dat = tmpaddr; 442 443 /* Remove the fbuf if it does not contains data */ 444 if (fbuf->fb_len == 0) { 445 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_in, fb_next); 446 stat_fbufs_in--; 447 SIMPLEQ_INSERT_TAIL(&fd->fd_fbufs_wait, fbuf, fb_next); 448 stat_fbufs_wait++; 449 } 450 451 end: 452 return (error); 453 } 454 455 int 456 fusewrite(dev_t dev, struct uio *uio, int ioflag) 457 { 458 struct fusebuf *lastfbuf; 459 struct fuse_d *fd; 460 struct fusebuf *fbuf; 461 struct fb_hdr hdr; 462 int error = 0; 463 464 fd = fuse_lookup(minor(dev)); 465 if (fd == NULL) 466 return (ENXIO); 467 468 /* We get the whole fusebuf or nothing */ 469 if (uio->uio_resid != FUSEBUFSIZE) 470 return (EINVAL); 471 472 if ((error = uiomove(&hdr, sizeof(hdr), uio)) != 0) 473 return (error); 474 475 /* looking for uuid in fd_fbufs_wait */ 476 SIMPLEQ_FOREACH(fbuf, &fd->fd_fbufs_wait, fb_next) { 477 if (fbuf->fb_uuid == hdr.fh_uuid) 478 break; 479 480 lastfbuf = fbuf; 481 } 482 if (fbuf == NULL) 483 return (EINVAL); 484 485 /* Update fb_hdr */ 486 fbuf->fb_len = hdr.fh_len; 487 fbuf->fb_err = hdr.fh_err; 488 fbuf->fb_ino = hdr.fh_ino; 489 490 /* Check for corrupted fbufs */ 491 if ((fbuf->fb_len && fbuf->fb_err) || 492 SIMPLEQ_EMPTY(&fd->fd_fbufs_wait)) { 493 printf("fuse: dropping corrupted fusebuf\n"); 494 error = EINVAL; 495 goto end; 496 } 497 498 /* Get the missing datas from the fbuf */ 499 error = uiomove(&fbuf->FD, uio->uio_resid, uio); 500 if (error) 501 return error; 502 fbuf->fb_dat = NULL; 503 #ifdef FUSE_DEBUG 504 fuse_dump_buff((char *)fbuf, FUSEBUFSIZE); 505 #endif 506 507 switch (fbuf->fb_type) { 508 case FBT_INIT: 509 fd->fd_fmp->sess_init = 1; 510 break ; 511 case FBT_DESTROY: 512 fd->fd_fmp = NULL; 513 break ; 514 } 515 end: 516 /* Remove the fbuf if it does not contains data */ 517 if (fbuf->fb_len == 0) { 518 if (fbuf == SIMPLEQ_FIRST(&fd->fd_fbufs_wait)) 519 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_wait, fb_next); 520 else 521 SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_wait, lastfbuf, 522 fb_next); 523 stat_fbufs_wait--; 524 if (fbuf->fb_type == FBT_INIT) 525 fb_delete(fbuf); 526 else 527 wakeup(fbuf); 528 } 529 530 return (error); 531 } 532 533 int 534 fusepoll(dev_t dev, int events, struct proc *p) 535 { 536 struct fuse_d *fd; 537 int revents = 0; 538 539 fd = fuse_lookup(minor(dev)); 540 if (fd == NULL) 541 return (EINVAL); 542 543 if (events & (POLLIN | POLLRDNORM)) 544 if (!SIMPLEQ_EMPTY(&fd->fd_fbufs_in)) 545 revents |= events & (POLLIN | POLLRDNORM); 546 547 if (events & (POLLOUT | POLLWRNORM)) 548 revents |= events & (POLLOUT | POLLWRNORM); 549 550 if (revents == 0) 551 if (events & (POLLIN | POLLRDNORM)) 552 selrecord(p, &fd->fd_rsel); 553 554 return (revents); 555 } 556 557 int 558 fusekqfilter(dev_t dev, struct knote *kn) 559 { 560 struct fuse_d *fd; 561 struct klist *klist; 562 563 fd = fuse_lookup(minor(dev)); 564 if (fd == NULL) 565 return (EINVAL); 566 567 switch (kn->kn_filter) { 568 case EVFILT_READ: 569 klist = &fd->fd_rsel.si_note; 570 kn->kn_fop = &fuse_rd_filtops; 571 break; 572 case EVFILT_WRITE: 573 klist = &fd->fd_rsel.si_note; 574 kn->kn_fop = &fuse_seltrue_filtops; 575 break; 576 default: 577 return (EINVAL); 578 } 579 580 kn->kn_hook = fd; 581 582 SLIST_INSERT_HEAD(klist, kn, kn_selnext); 583 584 return (0); 585 } 586 587 void 588 filt_fuse_rdetach(struct knote *kn) 589 { 590 struct fuse_d *fd = kn->kn_hook; 591 struct klist *klist = &fd->fd_rsel.si_note; 592 593 SLIST_REMOVE(klist, kn, knote, kn_selnext); 594 } 595 596 int 597 filt_fuse_read(struct knote *kn, long hint) 598 { 599 struct fuse_d *fd = kn->kn_hook; 600 int event = 0; 601 602 if (!SIMPLEQ_EMPTY(&fd->fd_fbufs_in)) 603 event = 1; 604 605 return (event); 606 } 607