1241519Sattilio/* 2241519Sattilio * Copyright (c) 2007-2009 Google Inc. and Amit Singh 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: releng/11.0/sys/fs/fuse/fuse_file.c 299872 2016-05-15 23:15:10Z rmacklem $"); 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/vnode.h> 75241519Sattilio#include <sys/sysctl.h> 76241519Sattilio 77241519Sattilio#include "fuse.h" 78241519Sattilio#include "fuse_file.h" 79241519Sattilio#include "fuse_internal.h" 80241519Sattilio#include "fuse_ipc.h" 81241519Sattilio#include "fuse_node.h" 82241519Sattilio 83241519Sattilio#define FUSE_DEBUG_MODULE FILE 84241519Sattilio#include "fuse_debug.h" 85241519Sattilio 86241519Sattiliostatic int fuse_fh_count = 0; 87241519Sattilio 88241519SattilioSYSCTL_INT(_vfs_fuse, OID_AUTO, filehandle_count, CTLFLAG_RD, 89241519Sattilio &fuse_fh_count, 0, ""); 90241519Sattilio 91241519Sattilioint 92241519Sattiliofuse_filehandle_open(struct vnode *vp, 93241519Sattilio fufh_type_t fufh_type, 94241519Sattilio struct fuse_filehandle **fufhp, 95241519Sattilio struct thread *td, 96241519Sattilio struct ucred *cred) 97241519Sattilio{ 98241519Sattilio struct fuse_dispatcher fdi; 99241519Sattilio struct fuse_open_in *foi; 100241519Sattilio struct fuse_open_out *foo; 101241519Sattilio 102241519Sattilio int err = 0; 103241519Sattilio int isdir = 0; 104241519Sattilio int oflags = 0; 105241519Sattilio int op = FUSE_OPEN; 106241519Sattilio 107241519Sattilio fuse_trace_printf("fuse_filehandle_open(vp=%p, fufh_type=%d)\n", 108241519Sattilio vp, fufh_type); 109241519Sattilio 110241519Sattilio if (fuse_filehandle_valid(vp, fufh_type)) { 111241519Sattilio panic("FUSE: filehandle_open called despite valid fufh (type=%d)", 112241519Sattilio fufh_type); 113241519Sattilio /* NOTREACHED */ 114241519Sattilio } 115241519Sattilio /* 116241519Sattilio * Note that this means we are effectively FILTERING OUT open() flags. 117241519Sattilio */ 118241519Sattilio oflags = fuse_filehandle_xlate_to_oflags(fufh_type); 119241519Sattilio 120241519Sattilio if (vnode_isdir(vp)) { 121241519Sattilio isdir = 1; 122241519Sattilio op = FUSE_OPENDIR; 123241519Sattilio if (fufh_type != FUFH_RDONLY) { 124241519Sattilio printf("FUSE:non-rdonly fh requested for a directory?\n"); 125241519Sattilio fufh_type = FUFH_RDONLY; 126241519Sattilio } 127241519Sattilio } 128241519Sattilio fdisp_init(&fdi, sizeof(*foi)); 129241519Sattilio fdisp_make_vp(&fdi, op, vp, td, cred); 130241519Sattilio 131241519Sattilio foi = fdi.indata; 132241519Sattilio foi->flags = oflags; 133241519Sattilio 134241519Sattilio if ((err = fdisp_wait_answ(&fdi))) { 135241519Sattilio debug_printf("OUCH ... daemon didn't give fh (err = %d)\n", err); 136241519Sattilio if (err == ENOENT) { 137241519Sattilio fuse_internal_vnode_disappear(vp); 138241519Sattilio } 139241519Sattilio goto out; 140241519Sattilio } 141241519Sattilio foo = fdi.answ; 142241519Sattilio 143241519Sattilio fuse_filehandle_init(vp, fufh_type, fufhp, foo->fh); 144241519Sattilio 145299753Srmacklem /* 146299753Srmacklem * For WRONLY opens, force DIRECT_IO. This is necessary 147299753Srmacklem * since writing a partial block through the buffer cache 148299753Srmacklem * will result in a read of the block and that read won't 149299753Srmacklem * be allowed by the WRONLY open. 150299753Srmacklem */ 151299753Srmacklem if (fufh_type == FUFH_WRONLY) 152299753Srmacklem fuse_vnode_open(vp, foo->open_flags | FOPEN_DIRECT_IO, td); 153299753Srmacklem else 154299753Srmacklem fuse_vnode_open(vp, foo->open_flags, td); 155299753Srmacklem 156241519Sattilioout: 157241519Sattilio fdisp_destroy(&fdi); 158241519Sattilio return err; 159241519Sattilio} 160241519Sattilio 161241519Sattilioint 162241519Sattiliofuse_filehandle_close(struct vnode *vp, 163241519Sattilio fufh_type_t fufh_type, 164241519Sattilio struct thread *td, 165241519Sattilio struct ucred *cred) 166241519Sattilio{ 167241519Sattilio struct fuse_dispatcher fdi; 168241519Sattilio struct fuse_release_in *fri; 169241519Sattilio struct fuse_vnode_data *fvdat = VTOFUD(vp); 170241519Sattilio struct fuse_filehandle *fufh = NULL; 171241519Sattilio 172241519Sattilio int err = 0; 173241519Sattilio int isdir = 0; 174241519Sattilio int op = FUSE_RELEASE; 175241519Sattilio 176241519Sattilio fuse_trace_printf("fuse_filehandle_put(vp=%p, fufh_type=%d)\n", 177241519Sattilio vp, fufh_type); 178241519Sattilio 179241519Sattilio fufh = &(fvdat->fufh[fufh_type]); 180241519Sattilio if (!FUFH_IS_VALID(fufh)) { 181241519Sattilio panic("FUSE: filehandle_put called on invalid fufh (type=%d)", 182241519Sattilio fufh_type); 183241519Sattilio /* NOTREACHED */ 184241519Sattilio } 185241519Sattilio if (fuse_isdeadfs(vp)) { 186241519Sattilio goto out; 187241519Sattilio } 188241519Sattilio if (vnode_isdir(vp)) { 189241519Sattilio op = FUSE_RELEASEDIR; 190241519Sattilio isdir = 1; 191241519Sattilio } 192241519Sattilio fdisp_init(&fdi, sizeof(*fri)); 193241519Sattilio fdisp_make_vp(&fdi, op, vp, td, cred); 194241519Sattilio fri = fdi.indata; 195241519Sattilio fri->fh = fufh->fh_id; 196241519Sattilio fri->flags = fuse_filehandle_xlate_to_oflags(fufh_type); 197241519Sattilio 198241519Sattilio err = fdisp_wait_answ(&fdi); 199241519Sattilio fdisp_destroy(&fdi); 200241519Sattilio 201241519Sattilioout: 202241519Sattilio atomic_subtract_acq_int(&fuse_fh_count, 1); 203241519Sattilio fufh->fh_id = (uint64_t)-1; 204241519Sattilio fufh->fh_type = FUFH_INVALID; 205241519Sattilio 206241519Sattilio return err; 207241519Sattilio} 208241519Sattilio 209241519Sattilioint 210241519Sattiliofuse_filehandle_valid(struct vnode *vp, fufh_type_t fufh_type) 211241519Sattilio{ 212241519Sattilio struct fuse_vnode_data *fvdat = VTOFUD(vp); 213241519Sattilio struct fuse_filehandle *fufh; 214241519Sattilio 215241519Sattilio fufh = &(fvdat->fufh[fufh_type]); 216241519Sattilio return FUFH_IS_VALID(fufh); 217241519Sattilio} 218241519Sattilio 219299872Srmacklem/* 220299872Srmacklem * Check for a valid file handle, first the type requested, but if that 221299872Srmacklem * isn't valid, try for FUFH_RDWR. 222299872Srmacklem * Return the FUFH type that is valid or FUFH_INVALID if there are none. 223299872Srmacklem * This is a variant of fuse_filehandle_vaild() analogous to 224299872Srmacklem * fuse_filehandle_getrw(). 225299872Srmacklem */ 226299872Srmacklemfufh_type_t 227299872Srmacklemfuse_filehandle_validrw(struct vnode *vp, fufh_type_t fufh_type) 228299872Srmacklem{ 229299872Srmacklem struct fuse_vnode_data *fvdat = VTOFUD(vp); 230299872Srmacklem struct fuse_filehandle *fufh; 231299872Srmacklem 232299872Srmacklem fufh = &fvdat->fufh[fufh_type]; 233299872Srmacklem if (FUFH_IS_VALID(fufh) != 0) 234299872Srmacklem return (fufh_type); 235299872Srmacklem fufh = &fvdat->fufh[FUFH_RDWR]; 236299872Srmacklem if (FUFH_IS_VALID(fufh) != 0) 237299872Srmacklem return (FUFH_RDWR); 238299872Srmacklem return (FUFH_INVALID); 239299872Srmacklem} 240299872Srmacklem 241241519Sattilioint 242241519Sattiliofuse_filehandle_get(struct vnode *vp, fufh_type_t fufh_type, 243241519Sattilio struct fuse_filehandle **fufhp) 244241519Sattilio{ 245241519Sattilio struct fuse_vnode_data *fvdat = VTOFUD(vp); 246241519Sattilio struct fuse_filehandle *fufh; 247241519Sattilio 248241519Sattilio fufh = &(fvdat->fufh[fufh_type]); 249241519Sattilio if (!FUFH_IS_VALID(fufh)) 250241519Sattilio return EBADF; 251241519Sattilio if (fufhp != NULL) 252241519Sattilio *fufhp = fufh; 253241519Sattilio return 0; 254241519Sattilio} 255241519Sattilio 256241519Sattilioint 257241519Sattiliofuse_filehandle_getrw(struct vnode *vp, fufh_type_t fufh_type, 258241519Sattilio struct fuse_filehandle **fufhp) 259241519Sattilio{ 260241519Sattilio struct fuse_vnode_data *fvdat = VTOFUD(vp); 261241519Sattilio struct fuse_filehandle *fufh; 262241519Sattilio 263241519Sattilio fufh = &(fvdat->fufh[fufh_type]); 264241519Sattilio if (!FUFH_IS_VALID(fufh)) { 265241519Sattilio fufh_type = FUFH_RDWR; 266241519Sattilio } 267241519Sattilio return fuse_filehandle_get(vp, fufh_type, fufhp); 268241519Sattilio} 269241519Sattilio 270241519Sattiliovoid 271241519Sattiliofuse_filehandle_init(struct vnode *vp, 272241519Sattilio fufh_type_t fufh_type, 273241519Sattilio struct fuse_filehandle **fufhp, 274241519Sattilio uint64_t fh_id) 275241519Sattilio{ 276241519Sattilio struct fuse_vnode_data *fvdat = VTOFUD(vp); 277241519Sattilio struct fuse_filehandle *fufh; 278241519Sattilio 279241521Sattilio FS_DEBUG("id=%jd type=%d\n", (intmax_t)fh_id, fufh_type); 280241519Sattilio fufh = &(fvdat->fufh[fufh_type]); 281241519Sattilio MPASS(!FUFH_IS_VALID(fufh)); 282241519Sattilio fufh->fh_id = fh_id; 283241519Sattilio fufh->fh_type = fufh_type; 284241519Sattilio if (!FUFH_IS_VALID(fufh)) { 285241519Sattilio panic("FUSE: init: invalid filehandle id (type=%d)", fufh_type); 286241519Sattilio } 287241519Sattilio if (fufhp != NULL) 288241519Sattilio *fufhp = fufh; 289241519Sattilio 290241519Sattilio atomic_add_acq_int(&fuse_fh_count, 1); 291241519Sattilio} 292