1241519Sattilio/* 2241519Sattilio * Copyright (c) 2007-2009 Google Inc. 3241519Sattilio * All rights reserved. 4241519Sattilio * 5241519Sattilio * Redistribution and use in source and binary forms, with or without 6241519Sattilio * modification, are permitted provided that the following conditions are 7241519Sattilio * met: 8241519Sattilio * 9241519Sattilio * * Redistributions of source code must retain the above copyright 10241519Sattilio * notice, this list of conditions and the following disclaimer. 11241519Sattilio * * Redistributions in binary form must reproduce the above 12241519Sattilio * copyright notice, this list of conditions and the following disclaimer 13241519Sattilio * in the documentation and/or other materials provided with the 14241519Sattilio * distribution. 15241519Sattilio * * Neither the name of Google Inc. nor the names of its 16241519Sattilio * contributors may be used to endorse or promote products derived from 17241519Sattilio * this software without specific prior written permission. 18241519Sattilio * 19241519Sattilio * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20241519Sattilio * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21241519Sattilio * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22241519Sattilio * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23241519Sattilio * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24241519Sattilio * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25241519Sattilio * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26241519Sattilio * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27241519Sattilio * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28241519Sattilio * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29241519Sattilio * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30241519Sattilio * 31241519Sattilio * Copyright (C) 2005 Csaba Henk. 32241519Sattilio * All rights reserved. 33241519Sattilio * 34241519Sattilio * Redistribution and use in source and binary forms, with or without 35241519Sattilio * modification, are permitted provided that the following conditions 36241519Sattilio * are met: 37241519Sattilio * 1. Redistributions of source code must retain the above copyright 38241519Sattilio * notice, this list of conditions and the following disclaimer. 39241519Sattilio * 2. Redistributions in binary form must reproduce the above copyright 40241519Sattilio * notice, this list of conditions and the following disclaimer in the 41241519Sattilio * documentation and/or other materials provided with the distribution. 42241519Sattilio * 43241519Sattilio * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 44241519Sattilio * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 45241519Sattilio * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 46241519Sattilio * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 47241519Sattilio * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48241519Sattilio * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 49241519Sattilio * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 50241519Sattilio * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 51241519Sattilio * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 52241519Sattilio * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 53241519Sattilio * SUCH DAMAGE. 54241519Sattilio */ 55241519Sattilio 56241519Sattilio#include <sys/cdefs.h> 57241519Sattilio__FBSDID("$FreeBSD$"); 58241519Sattilio 59241519Sattilio#include <sys/types.h> 60241519Sattilio#include <sys/module.h> 61241519Sattilio#include <sys/systm.h> 62241519Sattilio#include <sys/errno.h> 63241519Sattilio#include <sys/param.h> 64241519Sattilio#include <sys/kernel.h> 65241519Sattilio#include <sys/conf.h> 66241519Sattilio#include <sys/uio.h> 67241519Sattilio#include <sys/malloc.h> 68241519Sattilio#include <sys/queue.h> 69241519Sattilio#include <sys/lock.h> 70241519Sattilio#include <sys/sx.h> 71241519Sattilio#include <sys/mutex.h> 72241519Sattilio#include <sys/proc.h> 73241519Sattilio#include <sys/mount.h> 74241519Sattilio#include <sys/stat.h> 75241519Sattilio#include <sys/fcntl.h> 76241519Sattilio#include <sys/sysctl.h> 77241519Sattilio#include <sys/poll.h> 78241519Sattilio#include <sys/selinfo.h> 79241519Sattilio 80241519Sattilio#include "fuse.h" 81241519Sattilio#include "fuse_ipc.h" 82241519Sattilio 83241519Sattilio#define FUSE_DEBUG_MODULE DEVICE 84241519Sattilio#include "fuse_debug.h" 85241519Sattilio 86241519Sattiliostatic struct cdev *fuse_dev; 87241519Sattilio 88241519Sattiliostatic d_open_t fuse_device_open; 89241519Sattiliostatic d_close_t fuse_device_close; 90241519Sattiliostatic d_poll_t fuse_device_poll; 91241519Sattiliostatic d_read_t fuse_device_read; 92241519Sattiliostatic d_write_t fuse_device_write; 93241519Sattilio 94241519Sattiliostatic struct cdevsw fuse_device_cdevsw = { 95241519Sattilio .d_open = fuse_device_open, 96241519Sattilio .d_close = fuse_device_close, 97241519Sattilio .d_name = "fuse", 98241519Sattilio .d_poll = fuse_device_poll, 99241519Sattilio .d_read = fuse_device_read, 100241519Sattilio .d_write = fuse_device_write, 101241519Sattilio .d_version = D_VERSION, 102241519Sattilio}; 103241519Sattilio 104241519Sattilio/**************************** 105241519Sattilio * 106241519Sattilio * >>> Fuse device op defs 107241519Sattilio * 108241519Sattilio ****************************/ 109241519Sattilio 110241519Sattiliostatic void 111241519Sattiliofdata_dtor(void *arg) 112241519Sattilio{ 113241519Sattilio struct fuse_data *fdata; 114241519Sattilio 115241519Sattilio fdata = arg; 116241519Sattilio fdata_trydestroy(fdata); 117241519Sattilio} 118241519Sattilio 119241519Sattilio/* 120241519Sattilio * Resources are set up on a per-open basis 121241519Sattilio */ 122241519Sattiliostatic int 123241519Sattiliofuse_device_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 124241519Sattilio{ 125241519Sattilio struct fuse_data *fdata; 126241519Sattilio int error; 127241519Sattilio 128241521Sattilio FS_DEBUG("device %p\n", dev); 129241519Sattilio 130241519Sattilio fdata = fdata_alloc(dev, td->td_ucred); 131241519Sattilio error = devfs_set_cdevpriv(fdata, fdata_dtor); 132241519Sattilio if (error != 0) 133241519Sattilio fdata_trydestroy(fdata); 134241519Sattilio else 135241521Sattilio FS_DEBUG("%s: device opened by thread %d.\n", dev->si_name, 136241519Sattilio td->td_tid); 137241519Sattilio return (error); 138241519Sattilio} 139241519Sattilio 140241519Sattiliostatic int 141241519Sattiliofuse_device_close(struct cdev *dev, int fflag, int devtype, struct thread *td) 142241519Sattilio{ 143241519Sattilio struct fuse_data *data; 144241519Sattilio struct fuse_ticket *tick; 145241519Sattilio int error; 146241519Sattilio 147241519Sattilio error = devfs_get_cdevpriv((void **)&data); 148241519Sattilio if (error != 0) 149241519Sattilio return (error); 150241519Sattilio if (!data) 151241519Sattilio panic("no fuse data upon fuse device close"); 152241519Sattilio fdata_set_dead(data); 153241519Sattilio 154241519Sattilio FUSE_LOCK(); 155241519Sattilio fuse_lck_mtx_lock(data->aw_mtx); 156241519Sattilio /* wakup poll()ers */ 157241519Sattilio selwakeuppri(&data->ks_rsel, PZERO + 1); 158241519Sattilio /* Don't let syscall handlers wait in vain */ 159241519Sattilio while ((tick = fuse_aw_pop(data))) { 160241519Sattilio fuse_lck_mtx_lock(tick->tk_aw_mtx); 161241519Sattilio fticket_set_answered(tick); 162241519Sattilio tick->tk_aw_errno = ENOTCONN; 163241519Sattilio wakeup(tick); 164241519Sattilio fuse_lck_mtx_unlock(tick->tk_aw_mtx); 165241519Sattilio FUSE_ASSERT_AW_DONE(tick); 166241519Sattilio fuse_ticket_drop(tick); 167241519Sattilio } 168241519Sattilio fuse_lck_mtx_unlock(data->aw_mtx); 169241519Sattilio FUSE_UNLOCK(); 170241519Sattilio 171241521Sattilio FS_DEBUG("%s: device closed by thread %d.\n", dev->si_name, td->td_tid); 172241519Sattilio return (0); 173241519Sattilio} 174241519Sattilio 175241519Sattilioint 176241519Sattiliofuse_device_poll(struct cdev *dev, int events, struct thread *td) 177241519Sattilio{ 178241519Sattilio struct fuse_data *data; 179241519Sattilio int error, revents = 0; 180241519Sattilio 181241519Sattilio error = devfs_get_cdevpriv((void **)&data); 182241519Sattilio if (error != 0) 183241519Sattilio return (events & 184241519Sattilio (POLLHUP|POLLIN|POLLRDNORM|POLLOUT|POLLWRNORM)); 185241519Sattilio 186241519Sattilio if (events & (POLLIN | POLLRDNORM)) { 187241519Sattilio fuse_lck_mtx_lock(data->ms_mtx); 188241519Sattilio if (fdata_get_dead(data) || STAILQ_FIRST(&data->ms_head)) 189241519Sattilio revents |= events & (POLLIN | POLLRDNORM); 190241519Sattilio else 191241519Sattilio selrecord(td, &data->ks_rsel); 192241519Sattilio fuse_lck_mtx_unlock(data->ms_mtx); 193241519Sattilio } 194241519Sattilio if (events & (POLLOUT | POLLWRNORM)) { 195241519Sattilio revents |= events & (POLLOUT | POLLWRNORM); 196241519Sattilio } 197241519Sattilio return (revents); 198241519Sattilio} 199241519Sattilio 200241519Sattilio/* 201241519Sattilio * fuse_device_read hangs on the queue of VFS messages. 202241519Sattilio * When it's notified that there is a new one, it picks that and 203241519Sattilio * passes up to the daemon 204241519Sattilio */ 205241519Sattilioint 206241519Sattiliofuse_device_read(struct cdev *dev, struct uio *uio, int ioflag) 207241519Sattilio{ 208241519Sattilio int err; 209241519Sattilio struct fuse_data *data; 210241519Sattilio struct fuse_ticket *tick; 211241519Sattilio void *buf[] = {NULL, NULL, NULL}; 212241519Sattilio int buflen[3]; 213241519Sattilio int i; 214241519Sattilio 215241521Sattilio FS_DEBUG("fuse device being read on thread %d\n", uio->uio_td->td_tid); 216241519Sattilio 217241519Sattilio err = devfs_get_cdevpriv((void **)&data); 218241519Sattilio if (err != 0) 219241519Sattilio return (err); 220241519Sattilio 221241519Sattilio fuse_lck_mtx_lock(data->ms_mtx); 222241519Sattilioagain: 223241519Sattilio if (fdata_get_dead(data)) { 224241521Sattilio FS_DEBUG2G("we know early on that reader should be kicked so we don't wait for news\n"); 225241519Sattilio fuse_lck_mtx_unlock(data->ms_mtx); 226241519Sattilio return (ENODEV); 227241519Sattilio } 228241519Sattilio if (!(tick = fuse_ms_pop(data))) { 229241519Sattilio /* check if we may block */ 230241519Sattilio if (ioflag & O_NONBLOCK) { 231241519Sattilio /* get outa here soon */ 232241519Sattilio fuse_lck_mtx_unlock(data->ms_mtx); 233241519Sattilio return (EAGAIN); 234241519Sattilio } else { 235241519Sattilio err = msleep(data, &data->ms_mtx, PCATCH, "fu_msg", 0); 236241519Sattilio if (err != 0) { 237241519Sattilio fuse_lck_mtx_unlock(data->ms_mtx); 238241519Sattilio return (fdata_get_dead(data) ? ENODEV : err); 239241519Sattilio } 240241519Sattilio tick = fuse_ms_pop(data); 241241519Sattilio } 242241519Sattilio } 243241519Sattilio if (!tick) { 244241519Sattilio /* 245241519Sattilio * We can get here if fuse daemon suddenly terminates, 246241519Sattilio * eg, by being hit by a SIGKILL 247241519Sattilio * -- and some other cases, too, tho not totally clear, when 248241519Sattilio * (cv_signal/wakeup_one signals the whole process ?) 249241519Sattilio */ 250241521Sattilio FS_DEBUG("no message on thread #%d\n", uio->uio_td->td_tid); 251241519Sattilio goto again; 252241519Sattilio } 253241519Sattilio fuse_lck_mtx_unlock(data->ms_mtx); 254241519Sattilio 255241519Sattilio if (fdata_get_dead(data)) { 256241519Sattilio /* 257241519Sattilio * somebody somewhere -- eg., umount routine -- 258241519Sattilio * wants this liaison finished off 259241519Sattilio */ 260241521Sattilio FS_DEBUG2G("reader is to be sacked\n"); 261241519Sattilio if (tick) { 262241521Sattilio FS_DEBUG2G("weird -- \"kick\" is set tho there is message\n"); 263241519Sattilio FUSE_ASSERT_MS_DONE(tick); 264241519Sattilio fuse_ticket_drop(tick); 265241519Sattilio } 266241519Sattilio return (ENODEV); /* This should make the daemon get off 267241519Sattilio * of us */ 268241519Sattilio } 269241521Sattilio FS_DEBUG("message got on thread #%d\n", uio->uio_td->td_tid); 270241519Sattilio 271241519Sattilio KASSERT(tick->tk_ms_bufdata || tick->tk_ms_bufsize == 0, 272241519Sattilio ("non-null buf pointer with positive size")); 273241519Sattilio 274241519Sattilio switch (tick->tk_ms_type) { 275241519Sattilio case FT_M_FIOV: 276241519Sattilio buf[0] = tick->tk_ms_fiov.base; 277241519Sattilio buflen[0] = tick->tk_ms_fiov.len; 278241519Sattilio break; 279241519Sattilio case FT_M_BUF: 280241519Sattilio buf[0] = tick->tk_ms_fiov.base; 281241519Sattilio buflen[0] = tick->tk_ms_fiov.len; 282241519Sattilio buf[1] = tick->tk_ms_bufdata; 283241519Sattilio buflen[1] = tick->tk_ms_bufsize; 284241519Sattilio break; 285241519Sattilio default: 286241519Sattilio panic("unknown message type for fuse_ticket %p", tick); 287241519Sattilio } 288241519Sattilio 289241519Sattilio for (i = 0; buf[i]; i++) { 290241519Sattilio /* 291241519Sattilio * Why not ban mercilessly stupid daemons who can't keep up 292241519Sattilio * with us? (There is no much use of a partial read here...) 293241519Sattilio */ 294241519Sattilio /* 295241519Sattilio * XXX note that in such cases Linux FUSE throws EIO at the 296241519Sattilio * syscall invoker and stands back to the message queue. The 297241519Sattilio * rationale should be made clear (and possibly adopt that 298241519Sattilio * behaviour). Keeping the current scheme at least makes 299241519Sattilio * fallacy as loud as possible... 300241519Sattilio */ 301241519Sattilio if (uio->uio_resid < buflen[i]) { 302241519Sattilio fdata_set_dead(data); 303241521Sattilio FS_DEBUG2G("daemon is stupid, kick it off...\n"); 304241519Sattilio err = ENODEV; 305241519Sattilio break; 306241519Sattilio } 307241519Sattilio err = uiomove(buf[i], buflen[i], uio); 308241519Sattilio if (err) 309241519Sattilio break; 310241519Sattilio } 311241519Sattilio 312241519Sattilio FUSE_ASSERT_MS_DONE(tick); 313241519Sattilio fuse_ticket_drop(tick); 314241519Sattilio 315241519Sattilio return (err); 316241519Sattilio} 317241519Sattilio 318241519Sattiliostatic __inline int 319241519Sattiliofuse_ohead_audit(struct fuse_out_header *ohead, struct uio *uio) 320241519Sattilio{ 321241521Sattilio FS_DEBUG("Out header -- len: %i, error: %i, unique: %llu; iovecs: %d\n", 322241519Sattilio ohead->len, ohead->error, (unsigned long long)ohead->unique, 323241519Sattilio uio->uio_iovcnt); 324241519Sattilio 325241519Sattilio if (uio->uio_resid + sizeof(struct fuse_out_header) != ohead->len) { 326241521Sattilio FS_DEBUG("Format error: body size differs from size claimed by header\n"); 327241519Sattilio return (EINVAL); 328241519Sattilio } 329241519Sattilio if (uio->uio_resid && ohead->error) { 330241521Sattilio FS_DEBUG("Format error: non zero error but message had a body\n"); 331241519Sattilio return (EINVAL); 332241519Sattilio } 333241519Sattilio /* Sanitize the linuxism of negative errnos */ 334241519Sattilio ohead->error = -(ohead->error); 335241519Sattilio 336241519Sattilio return (0); 337241519Sattilio} 338241519Sattilio 339241519Sattilio/* 340241519Sattilio * fuse_device_write first reads the header sent by the daemon. 341241519Sattilio * If that's OK, looks up ticket/callback node by the unique id seen in header. 342241519Sattilio * If the callback node contains a handler function, the uio is passed over 343241519Sattilio * that. 344241519Sattilio */ 345241519Sattiliostatic int 346241519Sattiliofuse_device_write(struct cdev *dev, struct uio *uio, int ioflag) 347241519Sattilio{ 348241519Sattilio struct fuse_out_header ohead; 349241519Sattilio int err = 0; 350241519Sattilio struct fuse_data *data; 351241519Sattilio struct fuse_ticket *tick, *x_tick; 352241519Sattilio int found = 0; 353241519Sattilio 354241521Sattilio FS_DEBUG("resid: %zd, iovcnt: %d, thread: %d\n", 355241519Sattilio uio->uio_resid, uio->uio_iovcnt, uio->uio_td->td_tid); 356241519Sattilio 357241519Sattilio err = devfs_get_cdevpriv((void **)&data); 358241519Sattilio if (err != 0) 359241519Sattilio return (err); 360241519Sattilio 361241519Sattilio if (uio->uio_resid < sizeof(struct fuse_out_header)) { 362241521Sattilio FS_DEBUG("got less than a header!\n"); 363241519Sattilio fdata_set_dead(data); 364241519Sattilio return (EINVAL); 365241519Sattilio } 366241519Sattilio if ((err = uiomove(&ohead, sizeof(struct fuse_out_header), uio)) != 0) 367241519Sattilio return (err); 368241519Sattilio 369241519Sattilio /* 370241519Sattilio * We check header information (which is redundant) and compare it 371241519Sattilio * with what we see. If we see some inconsistency we discard the 372241519Sattilio * whole answer and proceed on as if it had never existed. In 373241519Sattilio * particular, no pretender will be woken up, regardless the 374241519Sattilio * "unique" value in the header. 375241519Sattilio */ 376241519Sattilio if ((err = fuse_ohead_audit(&ohead, uio))) { 377241519Sattilio fdata_set_dead(data); 378241519Sattilio return (err); 379241519Sattilio } 380241519Sattilio /* Pass stuff over to callback if there is one installed */ 381241519Sattilio 382241519Sattilio /* Looking for ticket with the unique id of header */ 383241519Sattilio fuse_lck_mtx_lock(data->aw_mtx); 384241519Sattilio TAILQ_FOREACH_SAFE(tick, &data->aw_head, tk_aw_link, 385241519Sattilio x_tick) { 386241521Sattilio FS_DEBUG("bumped into callback #%llu\n", 387241519Sattilio (unsigned long long)tick->tk_unique); 388241519Sattilio if (tick->tk_unique == ohead.unique) { 389241519Sattilio found = 1; 390241519Sattilio fuse_aw_remove(tick); 391241519Sattilio break; 392241519Sattilio } 393241519Sattilio } 394241519Sattilio fuse_lck_mtx_unlock(data->aw_mtx); 395241519Sattilio 396241519Sattilio if (found) { 397241519Sattilio if (tick->tk_aw_handler) { 398241519Sattilio /* 399241519Sattilio * We found a callback with proper handler. In this 400241519Sattilio * case the out header will be 0wnd by the callback, 401241519Sattilio * so the fun of freeing that is left for her. 402241519Sattilio * (Then, by all chance, she'll just get that's done 403241519Sattilio * via ticket_drop(), so no manual mucking 404241519Sattilio * around...) 405241519Sattilio */ 406241521Sattilio FS_DEBUG("pass ticket to a callback\n"); 407241519Sattilio memcpy(&tick->tk_aw_ohead, &ohead, sizeof(ohead)); 408241519Sattilio err = tick->tk_aw_handler(tick, uio); 409241519Sattilio } else { 410241519Sattilio /* pretender doesn't wanna do anything with answer */ 411241521Sattilio FS_DEBUG("stuff devalidated, so we drop it\n"); 412241519Sattilio } 413241519Sattilio 414241519Sattilio /* 415241519Sattilio * As aw_mtx was not held during the callback execution the 416241519Sattilio * ticket may have been inserted again. However, this is safe 417241519Sattilio * because fuse_ticket_drop() will deal with refcount anyway. 418241519Sattilio */ 419241519Sattilio fuse_ticket_drop(tick); 420241519Sattilio } else { 421241519Sattilio /* no callback at all! */ 422241521Sattilio FS_DEBUG("erhm, no handler for this response\n"); 423241519Sattilio err = EINVAL; 424241519Sattilio } 425241519Sattilio 426241519Sattilio return (err); 427241519Sattilio} 428241519Sattilio 429241519Sattilioint 430241519Sattiliofuse_device_init(void) 431241519Sattilio{ 432241519Sattilio 433241519Sattilio fuse_dev = make_dev(&fuse_device_cdevsw, 0, UID_ROOT, GID_OPERATOR, 434241519Sattilio S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, "fuse"); 435241519Sattilio if (fuse_dev == NULL) 436241519Sattilio return (ENOMEM); 437241519Sattilio return (0); 438241519Sattilio} 439241519Sattilio 440241519Sattiliovoid 441241519Sattiliofuse_device_destroy(void) 442241519Sattilio{ 443241519Sattilio 444241519Sattilio MPASS(fuse_dev != NULL); 445241519Sattilio destroy_dev(fuse_dev); 446241519Sattilio} 447