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$");
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	fuse_vnode_open(vp, foo->open_flags, td);
145241519Sattilio
146241519Sattilioout:
147241519Sattilio	fdisp_destroy(&fdi);
148241519Sattilio	return err;
149241519Sattilio}
150241519Sattilio
151241519Sattilioint
152241519Sattiliofuse_filehandle_close(struct vnode *vp,
153241519Sattilio    fufh_type_t fufh_type,
154241519Sattilio    struct thread *td,
155241519Sattilio    struct ucred *cred)
156241519Sattilio{
157241519Sattilio	struct fuse_dispatcher fdi;
158241519Sattilio	struct fuse_release_in *fri;
159241519Sattilio	struct fuse_vnode_data *fvdat = VTOFUD(vp);
160241519Sattilio	struct fuse_filehandle *fufh = NULL;
161241519Sattilio
162241519Sattilio	int err = 0;
163241519Sattilio	int isdir = 0;
164241519Sattilio	int op = FUSE_RELEASE;
165241519Sattilio
166241519Sattilio	fuse_trace_printf("fuse_filehandle_put(vp=%p, fufh_type=%d)\n",
167241519Sattilio	    vp, fufh_type);
168241519Sattilio
169241519Sattilio	fufh = &(fvdat->fufh[fufh_type]);
170241519Sattilio	if (!FUFH_IS_VALID(fufh)) {
171241519Sattilio		panic("FUSE: filehandle_put called on invalid fufh (type=%d)",
172241519Sattilio		    fufh_type);
173241519Sattilio		/* NOTREACHED */
174241519Sattilio	}
175241519Sattilio	if (fuse_isdeadfs(vp)) {
176241519Sattilio		goto out;
177241519Sattilio	}
178241519Sattilio	if (vnode_isdir(vp)) {
179241519Sattilio		op = FUSE_RELEASEDIR;
180241519Sattilio		isdir = 1;
181241519Sattilio	}
182241519Sattilio	fdisp_init(&fdi, sizeof(*fri));
183241519Sattilio	fdisp_make_vp(&fdi, op, vp, td, cred);
184241519Sattilio	fri = fdi.indata;
185241519Sattilio	fri->fh = fufh->fh_id;
186241519Sattilio	fri->flags = fuse_filehandle_xlate_to_oflags(fufh_type);
187241519Sattilio
188241519Sattilio	err = fdisp_wait_answ(&fdi);
189241519Sattilio	fdisp_destroy(&fdi);
190241519Sattilio
191241519Sattilioout:
192241519Sattilio	atomic_subtract_acq_int(&fuse_fh_count, 1);
193241519Sattilio	fufh->fh_id = (uint64_t)-1;
194241519Sattilio	fufh->fh_type = FUFH_INVALID;
195241519Sattilio
196241519Sattilio	return err;
197241519Sattilio}
198241519Sattilio
199241519Sattilioint
200241519Sattiliofuse_filehandle_valid(struct vnode *vp, fufh_type_t fufh_type)
201241519Sattilio{
202241519Sattilio	struct fuse_vnode_data *fvdat = VTOFUD(vp);
203241519Sattilio	struct fuse_filehandle *fufh;
204241519Sattilio
205241519Sattilio	fufh = &(fvdat->fufh[fufh_type]);
206241519Sattilio	return FUFH_IS_VALID(fufh);
207241519Sattilio}
208241519Sattilio
209241519Sattilioint
210241519Sattiliofuse_filehandle_get(struct vnode *vp, fufh_type_t fufh_type,
211241519Sattilio    struct fuse_filehandle **fufhp)
212241519Sattilio{
213241519Sattilio	struct fuse_vnode_data *fvdat = VTOFUD(vp);
214241519Sattilio	struct fuse_filehandle *fufh;
215241519Sattilio
216241519Sattilio	fufh = &(fvdat->fufh[fufh_type]);
217241519Sattilio	if (!FUFH_IS_VALID(fufh))
218241519Sattilio		return EBADF;
219241519Sattilio	if (fufhp != NULL)
220241519Sattilio		*fufhp = fufh;
221241519Sattilio	return 0;
222241519Sattilio}
223241519Sattilio
224241519Sattilioint
225241519Sattiliofuse_filehandle_getrw(struct vnode *vp, fufh_type_t fufh_type,
226241519Sattilio    struct fuse_filehandle **fufhp)
227241519Sattilio{
228241519Sattilio	struct fuse_vnode_data *fvdat = VTOFUD(vp);
229241519Sattilio	struct fuse_filehandle *fufh;
230241519Sattilio
231241519Sattilio	fufh = &(fvdat->fufh[fufh_type]);
232241519Sattilio	if (!FUFH_IS_VALID(fufh)) {
233241519Sattilio		fufh_type = FUFH_RDWR;
234241519Sattilio	}
235241519Sattilio	return fuse_filehandle_get(vp, fufh_type, fufhp);
236241519Sattilio}
237241519Sattilio
238241519Sattiliovoid
239241519Sattiliofuse_filehandle_init(struct vnode *vp,
240241519Sattilio    fufh_type_t fufh_type,
241241519Sattilio    struct fuse_filehandle **fufhp,
242241519Sattilio    uint64_t fh_id)
243241519Sattilio{
244241519Sattilio	struct fuse_vnode_data *fvdat = VTOFUD(vp);
245241519Sattilio	struct fuse_filehandle *fufh;
246241519Sattilio
247241521Sattilio	FS_DEBUG("id=%jd type=%d\n", (intmax_t)fh_id, fufh_type);
248241519Sattilio	fufh = &(fvdat->fufh[fufh_type]);
249241519Sattilio	MPASS(!FUFH_IS_VALID(fufh));
250241519Sattilio	fufh->fh_id = fh_id;
251241519Sattilio	fufh->fh_type = fufh_type;
252241519Sattilio	if (!FUFH_IS_VALID(fufh)) {
253241519Sattilio		panic("FUSE: init: invalid filehandle id (type=%d)", fufh_type);
254241519Sattilio	}
255241519Sattilio	if (fufhp != NULL)
256241519Sattilio		*fufhp = fufh;
257241519Sattilio
258241519Sattilio	atomic_add_acq_int(&fuse_fh_count, 1);
259241519Sattilio}
260