1/* 2 * Copyright (c) 2007-2009 Google Inc. and Amit Singh 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * Copyright (C) 2005 Csaba Henk. 32 * All rights reserved. 33 * 34 * Redistribution and use in source and binary forms, with or without 35 * modification, are permitted provided that the following conditions 36 * are met: 37 * 1. Redistributions of source code must retain the above copyright 38 * notice, this list of conditions and the following disclaimer. 39 * 2. Redistributions in binary form must reproduce the above copyright 40 * notice, this list of conditions and the following disclaimer in the 41 * documentation and/or other materials provided with the distribution. 42 * 43 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 46 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 53 * SUCH DAMAGE. 54 */ 55 56#include <sys/cdefs.h>
| 1/* 2 * Copyright (c) 2007-2009 Google Inc. and Amit Singh 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * Copyright (C) 2005 Csaba Henk. 32 * All rights reserved. 33 * 34 * Redistribution and use in source and binary forms, with or without 35 * modification, are permitted provided that the following conditions 36 * are met: 37 * 1. Redistributions of source code must retain the above copyright 38 * notice, this list of conditions and the following disclaimer. 39 * 2. Redistributions in binary form must reproduce the above copyright 40 * notice, this list of conditions and the following disclaimer in the 41 * documentation and/or other materials provided with the distribution. 42 * 43 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 46 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 53 * SUCH DAMAGE. 54 */ 55 56#include <sys/cdefs.h>
|
57__FBSDID("$FreeBSD: head/sys/fs/fuse/fuse_file.c 242727 2012-11-08 00:32:49Z attilio $");
| 57__FBSDID("$FreeBSD: head/sys/fs/fuse/fuse_file.c 299753 2016-05-14 20:03:22Z rmacklem $");
|
58 59#include <sys/types.h> 60#include <sys/module.h> 61#include <sys/systm.h> 62#include <sys/errno.h> 63#include <sys/param.h> 64#include <sys/kernel.h> 65#include <sys/conf.h> 66#include <sys/uio.h> 67#include <sys/malloc.h> 68#include <sys/queue.h> 69#include <sys/lock.h> 70#include <sys/sx.h> 71#include <sys/mutex.h> 72#include <sys/proc.h> 73#include <sys/mount.h> 74#include <sys/vnode.h> 75#include <sys/sysctl.h> 76 77#include "fuse.h" 78#include "fuse_file.h" 79#include "fuse_internal.h" 80#include "fuse_ipc.h" 81#include "fuse_node.h" 82 83#define FUSE_DEBUG_MODULE FILE 84#include "fuse_debug.h" 85 86static int fuse_fh_count = 0; 87 88SYSCTL_INT(_vfs_fuse, OID_AUTO, filehandle_count, CTLFLAG_RD, 89 &fuse_fh_count, 0, ""); 90 91int 92fuse_filehandle_open(struct vnode *vp, 93 fufh_type_t fufh_type, 94 struct fuse_filehandle **fufhp, 95 struct thread *td, 96 struct ucred *cred) 97{ 98 struct fuse_dispatcher fdi; 99 struct fuse_open_in *foi; 100 struct fuse_open_out *foo; 101 102 int err = 0; 103 int isdir = 0; 104 int oflags = 0; 105 int op = FUSE_OPEN; 106 107 fuse_trace_printf("fuse_filehandle_open(vp=%p, fufh_type=%d)\n", 108 vp, fufh_type); 109 110 if (fuse_filehandle_valid(vp, fufh_type)) { 111 panic("FUSE: filehandle_open called despite valid fufh (type=%d)", 112 fufh_type); 113 /* NOTREACHED */ 114 } 115 /* 116 * Note that this means we are effectively FILTERING OUT open() flags. 117 */ 118 oflags = fuse_filehandle_xlate_to_oflags(fufh_type); 119 120 if (vnode_isdir(vp)) { 121 isdir = 1; 122 op = FUSE_OPENDIR; 123 if (fufh_type != FUFH_RDONLY) { 124 printf("FUSE:non-rdonly fh requested for a directory?\n"); 125 fufh_type = FUFH_RDONLY; 126 } 127 } 128 fdisp_init(&fdi, sizeof(*foi)); 129 fdisp_make_vp(&fdi, op, vp, td, cred); 130 131 foi = fdi.indata; 132 foi->flags = oflags; 133 134 if ((err = fdisp_wait_answ(&fdi))) { 135 debug_printf("OUCH ... daemon didn't give fh (err = %d)\n", err); 136 if (err == ENOENT) { 137 fuse_internal_vnode_disappear(vp); 138 } 139 goto out; 140 } 141 foo = fdi.answ; 142 143 fuse_filehandle_init(vp, fufh_type, fufhp, foo->fh);
| 58 59#include <sys/types.h> 60#include <sys/module.h> 61#include <sys/systm.h> 62#include <sys/errno.h> 63#include <sys/param.h> 64#include <sys/kernel.h> 65#include <sys/conf.h> 66#include <sys/uio.h> 67#include <sys/malloc.h> 68#include <sys/queue.h> 69#include <sys/lock.h> 70#include <sys/sx.h> 71#include <sys/mutex.h> 72#include <sys/proc.h> 73#include <sys/mount.h> 74#include <sys/vnode.h> 75#include <sys/sysctl.h> 76 77#include "fuse.h" 78#include "fuse_file.h" 79#include "fuse_internal.h" 80#include "fuse_ipc.h" 81#include "fuse_node.h" 82 83#define FUSE_DEBUG_MODULE FILE 84#include "fuse_debug.h" 85 86static int fuse_fh_count = 0; 87 88SYSCTL_INT(_vfs_fuse, OID_AUTO, filehandle_count, CTLFLAG_RD, 89 &fuse_fh_count, 0, ""); 90 91int 92fuse_filehandle_open(struct vnode *vp, 93 fufh_type_t fufh_type, 94 struct fuse_filehandle **fufhp, 95 struct thread *td, 96 struct ucred *cred) 97{ 98 struct fuse_dispatcher fdi; 99 struct fuse_open_in *foi; 100 struct fuse_open_out *foo; 101 102 int err = 0; 103 int isdir = 0; 104 int oflags = 0; 105 int op = FUSE_OPEN; 106 107 fuse_trace_printf("fuse_filehandle_open(vp=%p, fufh_type=%d)\n", 108 vp, fufh_type); 109 110 if (fuse_filehandle_valid(vp, fufh_type)) { 111 panic("FUSE: filehandle_open called despite valid fufh (type=%d)", 112 fufh_type); 113 /* NOTREACHED */ 114 } 115 /* 116 * Note that this means we are effectively FILTERING OUT open() flags. 117 */ 118 oflags = fuse_filehandle_xlate_to_oflags(fufh_type); 119 120 if (vnode_isdir(vp)) { 121 isdir = 1; 122 op = FUSE_OPENDIR; 123 if (fufh_type != FUFH_RDONLY) { 124 printf("FUSE:non-rdonly fh requested for a directory?\n"); 125 fufh_type = FUFH_RDONLY; 126 } 127 } 128 fdisp_init(&fdi, sizeof(*foi)); 129 fdisp_make_vp(&fdi, op, vp, td, cred); 130 131 foi = fdi.indata; 132 foi->flags = oflags; 133 134 if ((err = fdisp_wait_answ(&fdi))) { 135 debug_printf("OUCH ... daemon didn't give fh (err = %d)\n", err); 136 if (err == ENOENT) { 137 fuse_internal_vnode_disappear(vp); 138 } 139 goto out; 140 } 141 foo = fdi.answ; 142 143 fuse_filehandle_init(vp, fufh_type, fufhp, foo->fh);
|
144 fuse_vnode_open(vp, foo->open_flags, td);
| |
145
| 144
|
| 145 /* 146 * For WRONLY opens, force DIRECT_IO. This is necessary 147 * since writing a partial block through the buffer cache 148 * will result in a read of the block and that read won't 149 * be allowed by the WRONLY open. 150 */ 151 if (fufh_type == FUFH_WRONLY) 152 fuse_vnode_open(vp, foo->open_flags | FOPEN_DIRECT_IO, td); 153 else 154 fuse_vnode_open(vp, foo->open_flags, td); 155
|
146out: 147 fdisp_destroy(&fdi); 148 return err; 149} 150 151int 152fuse_filehandle_close(struct vnode *vp, 153 fufh_type_t fufh_type, 154 struct thread *td, 155 struct ucred *cred) 156{ 157 struct fuse_dispatcher fdi; 158 struct fuse_release_in *fri; 159 struct fuse_vnode_data *fvdat = VTOFUD(vp); 160 struct fuse_filehandle *fufh = NULL; 161 162 int err = 0; 163 int isdir = 0; 164 int op = FUSE_RELEASE; 165 166 fuse_trace_printf("fuse_filehandle_put(vp=%p, fufh_type=%d)\n", 167 vp, fufh_type); 168 169 fufh = &(fvdat->fufh[fufh_type]); 170 if (!FUFH_IS_VALID(fufh)) { 171 panic("FUSE: filehandle_put called on invalid fufh (type=%d)", 172 fufh_type); 173 /* NOTREACHED */ 174 } 175 if (fuse_isdeadfs(vp)) { 176 goto out; 177 } 178 if (vnode_isdir(vp)) { 179 op = FUSE_RELEASEDIR; 180 isdir = 1; 181 } 182 fdisp_init(&fdi, sizeof(*fri)); 183 fdisp_make_vp(&fdi, op, vp, td, cred); 184 fri = fdi.indata; 185 fri->fh = fufh->fh_id; 186 fri->flags = fuse_filehandle_xlate_to_oflags(fufh_type); 187 188 err = fdisp_wait_answ(&fdi); 189 fdisp_destroy(&fdi); 190 191out: 192 atomic_subtract_acq_int(&fuse_fh_count, 1); 193 fufh->fh_id = (uint64_t)-1; 194 fufh->fh_type = FUFH_INVALID; 195 196 return err; 197} 198 199int 200fuse_filehandle_valid(struct vnode *vp, fufh_type_t fufh_type) 201{ 202 struct fuse_vnode_data *fvdat = VTOFUD(vp); 203 struct fuse_filehandle *fufh; 204 205 fufh = &(fvdat->fufh[fufh_type]); 206 return FUFH_IS_VALID(fufh); 207} 208 209int 210fuse_filehandle_get(struct vnode *vp, fufh_type_t fufh_type, 211 struct fuse_filehandle **fufhp) 212{ 213 struct fuse_vnode_data *fvdat = VTOFUD(vp); 214 struct fuse_filehandle *fufh; 215 216 fufh = &(fvdat->fufh[fufh_type]); 217 if (!FUFH_IS_VALID(fufh)) 218 return EBADF; 219 if (fufhp != NULL) 220 *fufhp = fufh; 221 return 0; 222} 223 224int 225fuse_filehandle_getrw(struct vnode *vp, fufh_type_t fufh_type, 226 struct fuse_filehandle **fufhp) 227{ 228 struct fuse_vnode_data *fvdat = VTOFUD(vp); 229 struct fuse_filehandle *fufh; 230 231 fufh = &(fvdat->fufh[fufh_type]); 232 if (!FUFH_IS_VALID(fufh)) { 233 fufh_type = FUFH_RDWR; 234 } 235 return fuse_filehandle_get(vp, fufh_type, fufhp); 236} 237 238void 239fuse_filehandle_init(struct vnode *vp, 240 fufh_type_t fufh_type, 241 struct fuse_filehandle **fufhp, 242 uint64_t fh_id) 243{ 244 struct fuse_vnode_data *fvdat = VTOFUD(vp); 245 struct fuse_filehandle *fufh; 246 247 FS_DEBUG("id=%jd type=%d\n", (intmax_t)fh_id, fufh_type); 248 fufh = &(fvdat->fufh[fufh_type]); 249 MPASS(!FUFH_IS_VALID(fufh)); 250 fufh->fh_id = fh_id; 251 fufh->fh_type = fufh_type; 252 if (!FUFH_IS_VALID(fufh)) { 253 panic("FUSE: init: invalid filehandle id (type=%d)", fufh_type); 254 } 255 if (fufhp != NULL) 256 *fufhp = fufh; 257 258 atomic_add_acq_int(&fuse_fh_count, 1); 259}
| 156out: 157 fdisp_destroy(&fdi); 158 return err; 159} 160 161int 162fuse_filehandle_close(struct vnode *vp, 163 fufh_type_t fufh_type, 164 struct thread *td, 165 struct ucred *cred) 166{ 167 struct fuse_dispatcher fdi; 168 struct fuse_release_in *fri; 169 struct fuse_vnode_data *fvdat = VTOFUD(vp); 170 struct fuse_filehandle *fufh = NULL; 171 172 int err = 0; 173 int isdir = 0; 174 int op = FUSE_RELEASE; 175 176 fuse_trace_printf("fuse_filehandle_put(vp=%p, fufh_type=%d)\n", 177 vp, fufh_type); 178 179 fufh = &(fvdat->fufh[fufh_type]); 180 if (!FUFH_IS_VALID(fufh)) { 181 panic("FUSE: filehandle_put called on invalid fufh (type=%d)", 182 fufh_type); 183 /* NOTREACHED */ 184 } 185 if (fuse_isdeadfs(vp)) { 186 goto out; 187 } 188 if (vnode_isdir(vp)) { 189 op = FUSE_RELEASEDIR; 190 isdir = 1; 191 } 192 fdisp_init(&fdi, sizeof(*fri)); 193 fdisp_make_vp(&fdi, op, vp, td, cred); 194 fri = fdi.indata; 195 fri->fh = fufh->fh_id; 196 fri->flags = fuse_filehandle_xlate_to_oflags(fufh_type); 197 198 err = fdisp_wait_answ(&fdi); 199 fdisp_destroy(&fdi); 200 201out: 202 atomic_subtract_acq_int(&fuse_fh_count, 1); 203 fufh->fh_id = (uint64_t)-1; 204 fufh->fh_type = FUFH_INVALID; 205 206 return err; 207} 208 209int 210fuse_filehandle_valid(struct vnode *vp, fufh_type_t fufh_type) 211{ 212 struct fuse_vnode_data *fvdat = VTOFUD(vp); 213 struct fuse_filehandle *fufh; 214 215 fufh = &(fvdat->fufh[fufh_type]); 216 return FUFH_IS_VALID(fufh); 217} 218 219int 220fuse_filehandle_get(struct vnode *vp, fufh_type_t fufh_type, 221 struct fuse_filehandle **fufhp) 222{ 223 struct fuse_vnode_data *fvdat = VTOFUD(vp); 224 struct fuse_filehandle *fufh; 225 226 fufh = &(fvdat->fufh[fufh_type]); 227 if (!FUFH_IS_VALID(fufh)) 228 return EBADF; 229 if (fufhp != NULL) 230 *fufhp = fufh; 231 return 0; 232} 233 234int 235fuse_filehandle_getrw(struct vnode *vp, fufh_type_t fufh_type, 236 struct fuse_filehandle **fufhp) 237{ 238 struct fuse_vnode_data *fvdat = VTOFUD(vp); 239 struct fuse_filehandle *fufh; 240 241 fufh = &(fvdat->fufh[fufh_type]); 242 if (!FUFH_IS_VALID(fufh)) { 243 fufh_type = FUFH_RDWR; 244 } 245 return fuse_filehandle_get(vp, fufh_type, fufhp); 246} 247 248void 249fuse_filehandle_init(struct vnode *vp, 250 fufh_type_t fufh_type, 251 struct fuse_filehandle **fufhp, 252 uint64_t fh_id) 253{ 254 struct fuse_vnode_data *fvdat = VTOFUD(vp); 255 struct fuse_filehandle *fufh; 256 257 FS_DEBUG("id=%jd type=%d\n", (intmax_t)fh_id, fufh_type); 258 fufh = &(fvdat->fufh[fufh_type]); 259 MPASS(!FUFH_IS_VALID(fufh)); 260 fufh->fh_id = fh_id; 261 fufh->fh_type = fufh_type; 262 if (!FUFH_IS_VALID(fufh)) { 263 panic("FUSE: init: invalid filehandle id (type=%d)", fufh_type); 264 } 265 if (fufhp != NULL) 266 *fufhp = fufh; 267 268 atomic_add_acq_int(&fuse_fh_count, 1); 269}
|