Bug Summary

File:miscfs/fuse/fuse_device.c
Warning:line 218, column 7
Although the value stored to 'fd' is used in the enclosing expression, the value is never actually read from 'fd'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name fuse_device.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/miscfs/fuse/fuse_device.c
1/* $OpenBSD: fuse_device.c,v 1.36 2021/03/11 13:31:35 jsg 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/stat.h>
26#include <sys/statvfs.h>
27#include <sys/vnode.h>
28#include <sys/fusebuf.h>
29
30#include "fusefs_node.h"
31#include "fusefs.h"
32
33#ifdef FUSE_DEBUG
34#define DPRINTF(fmt, arg...) printf("%s: " fmt, "fuse", ##arg)
35#else
36#define DPRINTF(fmt, arg...)
37#endif
38
39SIMPLEQ_HEAD(fusebuf_head, fusebuf)struct fusebuf_head { struct fusebuf *sqh_first; struct fusebuf
**sqh_last; }
;
40
41struct fuse_d {
42 struct fusefs_mnt *fd_fmp;
43 int fd_unit;
44
45 /*fusebufs queues*/
46 struct fusebuf_head fd_fbufs_in;
47 struct fusebuf_head fd_fbufs_wait;
48
49 /* kq fields */
50 struct selinfo fd_rsel;
51 LIST_ENTRY(fuse_d)struct { struct fuse_d *le_next; struct fuse_d **le_prev; } fd_list;
52};
53
54int stat_fbufs_in = 0;
55int stat_fbufs_wait = 0;
56int stat_opened_fusedev = 0;
57
58LIST_HEAD(, fuse_d)struct { struct fuse_d *lh_first; } fuse_d_list;
59struct fuse_d *fuse_lookup(int);
60
61void fuseattach(int);
62int fuseopen(dev_t, int, int, struct proc *);
63int fuseclose(dev_t, int, int, struct proc *);
64int fuseioctl(dev_t, u_long, caddr_t, int, struct proc *);
65int fuseread(dev_t, struct uio *, int);
66int fusewrite(dev_t, struct uio *, int);
67int fusepoll(dev_t, int, struct proc *);
68int fusekqfilter(dev_t dev, struct knote *kn);
69int filt_fuse_read(struct knote *, long);
70void filt_fuse_rdetach(struct knote *);
71
72const static struct filterops fuse_rd_filtops = {
73 .f_flags = FILTEROP_ISFD0x00000001,
74 .f_attach = NULL((void *)0),
75 .f_detach = filt_fuse_rdetach,
76 .f_event = filt_fuse_read,
77};
78
79#ifdef FUSE_DEBUG
80static void
81fuse_dump_buff(char *buff, int len)
82{
83 char text[17];
84 int i;
85
86 if (len < 0) {
87 printf("invalid len: %d", len);
88 return;
89 }
90 if (buff == NULL((void *)0)) {
91 printf("invalid buff");
92 return;
93 }
94
95 memset(text, 0, 17)__builtin_memset((text), (0), (17));
96 for (i = 0; i < len; i++) {
97 if (i != 0 && (i % 16) == 0) {
98 printf(": %s\n", text);
99 memset(text, 0, 17)__builtin_memset((text), (0), (17));
100 }
101
102 printf("%.2x ", buff[i] & 0xff);
103
104 if (buff[i] > ' ' && buff[i] < '~')
105 text[i%16] = buff[i] & 0xff;
106 else
107 text[i%16] = '.';
108 }
109
110 if ((i % 16) != 0)
111 while ((i % 16) != 0) {
112 printf(" ");
113 i++;
114 }
115
116 printf(": %s\n", text);
117}
118#endif
119
120struct fuse_d *
121fuse_lookup(int unit)
122{
123 struct fuse_d *fd;
124
125 LIST_FOREACH(fd, &fuse_d_list, fd_list)for((fd) = ((&fuse_d_list)->lh_first); (fd)!= ((void *
)0); (fd) = ((fd)->fd_list.le_next))
126 if (fd->fd_unit == unit)
127 return (fd);
128 return (NULL((void *)0));
129}
130
131/*
132 * Cleanup all msgs from sc_fbufs_in and sc_fbufs_wait.
133 */
134void
135fuse_device_cleanup(dev_t dev)
136{
137 struct fuse_d *fd;
138 struct fusebuf *f, *ftmp, *lprev;
139
140 fd = fuse_lookup(minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
141 if (fd == NULL((void *)0))
142 return;
143
144 /* clear FIFO IN */
145 lprev = NULL((void *)0);
146 SIMPLEQ_FOREACH_SAFE(f, &fd->fd_fbufs_in, fb_next, ftmp)for ((f) = ((&fd->fd_fbufs_in)->sqh_first); (f) &&
((ftmp) = ((f)->fb_hdr.fh_next.sqe_next), 1); (f) = (ftmp
))
{
147 DPRINTF("cleanup unprocessed msg in sc_fbufs_in\n");
148 if (lprev == NULL((void *)0))
149 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_in, fb_next)do { if (((&fd->fd_fbufs_in)->sqh_first = (&fd->
fd_fbufs_in)->sqh_first->fb_hdr.fh_next.sqe_next) == ((
void *)0)) (&fd->fd_fbufs_in)->sqh_last = &(&
fd->fd_fbufs_in)->sqh_first; } while (0)
;
150 else
151 SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_in, lprev,do { if (((lprev)->fb_hdr.fh_next.sqe_next = (lprev)->fb_hdr
.fh_next.sqe_next->fb_hdr.fh_next.sqe_next) == ((void *)0)
) (&fd->fd_fbufs_in)->sqh_last = &(lprev)->fb_hdr
.fh_next.sqe_next; } while (0)
152 fb_next)do { if (((lprev)->fb_hdr.fh_next.sqe_next = (lprev)->fb_hdr
.fh_next.sqe_next->fb_hdr.fh_next.sqe_next) == ((void *)0)
) (&fd->fd_fbufs_in)->sqh_last = &(lprev)->fb_hdr
.fh_next.sqe_next; } while (0)
;
153
154 stat_fbufs_in--;
155 f->fb_errfb_hdr.fh_err = ENXIO6;
156 wakeup(f);
157 lprev = f;
158 }
159
160 /* clear FIFO WAIT*/
161 lprev = NULL((void *)0);
162 SIMPLEQ_FOREACH_SAFE(f, &fd->fd_fbufs_wait, fb_next, ftmp)for ((f) = ((&fd->fd_fbufs_wait)->sqh_first); (f) &&
((ftmp) = ((f)->fb_hdr.fh_next.sqe_next), 1); (f) = (ftmp
))
{
163 DPRINTF("umount unprocessed msg in sc_fbufs_wait\n");
164 if (lprev == NULL((void *)0))
165 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_wait, fb_next)do { if (((&fd->fd_fbufs_wait)->sqh_first = (&fd
->fd_fbufs_wait)->sqh_first->fb_hdr.fh_next.sqe_next
) == ((void *)0)) (&fd->fd_fbufs_wait)->sqh_last = &
(&fd->fd_fbufs_wait)->sqh_first; } while (0)
;
166 else
167 SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_wait, lprev,do { if (((lprev)->fb_hdr.fh_next.sqe_next = (lprev)->fb_hdr
.fh_next.sqe_next->fb_hdr.fh_next.sqe_next) == ((void *)0)
) (&fd->fd_fbufs_wait)->sqh_last = &(lprev)->
fb_hdr.fh_next.sqe_next; } while (0)
168 fb_next)do { if (((lprev)->fb_hdr.fh_next.sqe_next = (lprev)->fb_hdr
.fh_next.sqe_next->fb_hdr.fh_next.sqe_next) == ((void *)0)
) (&fd->fd_fbufs_wait)->sqh_last = &(lprev)->
fb_hdr.fh_next.sqe_next; } while (0)
;
169
170 stat_fbufs_wait--;
171 f->fb_errfb_hdr.fh_err = ENXIO6;
172 wakeup(f);
173 lprev = f;
174 }
175}
176
177void
178fuse_device_queue_fbuf(dev_t dev, struct fusebuf *fbuf)
179{
180 struct fuse_d *fd;
181
182 fd = fuse_lookup(minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
183 if (fd == NULL((void *)0))
184 return;
185
186 SIMPLEQ_INSERT_TAIL(&fd->fd_fbufs_in, fbuf, fb_next)do { (fbuf)->fb_hdr.fh_next.sqe_next = ((void *)0); *(&
fd->fd_fbufs_in)->sqh_last = (fbuf); (&fd->fd_fbufs_in
)->sqh_last = &(fbuf)->fb_hdr.fh_next.sqe_next; } while
(0)
;
187 stat_fbufs_in++;
188 selwakeup(&fd->fd_rsel);
189}
190
191void
192fuse_device_set_fmp(struct fusefs_mnt *fmp, int set)
193{
194 struct fuse_d *fd;
195
196 fd = fuse_lookup(minor(fmp->dev)((unsigned)((fmp->dev) & 0xff) | (((fmp->dev) &
0xffff0000) >> 8))
);
197 if (fd == NULL((void *)0))
198 return;
199
200 fd->fd_fmp = set ? fmp : NULL((void *)0);
201}
202
203void
204fuseattach(int num)
205{
206 LIST_INIT(&fuse_d_list)do { ((&fuse_d_list)->lh_first) = ((void *)0); } while
(0)
;
207}
208
209int
210fuseopen(dev_t dev, int flags, int fmt, struct proc * p)
211{
212 struct fuse_d *fd;
213 int unit = minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
;
214
215 if (flags & O_EXCL0x0800)
216 return (EBUSY16); /* No exclusive opens */
217
218 if ((fd = fuse_lookup(unit)) != NULL((void *)0))
Although the value stored to 'fd' is used in the enclosing expression, the value is never actually read from 'fd'
219 return (EBUSY16);
220
221 fd = malloc(sizeof(*fd), M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008);
222 fd->fd_unit = unit;
223 SIMPLEQ_INIT(&fd->fd_fbufs_in)do { (&fd->fd_fbufs_in)->sqh_first = ((void *)0); (
&fd->fd_fbufs_in)->sqh_last = &(&fd->fd_fbufs_in
)->sqh_first; } while (0)
;
224 SIMPLEQ_INIT(&fd->fd_fbufs_wait)do { (&fd->fd_fbufs_wait)->sqh_first = ((void *)0);
(&fd->fd_fbufs_wait)->sqh_last = &(&fd->
fd_fbufs_wait)->sqh_first; } while (0)
;
225 LIST_INSERT_HEAD(&fuse_d_list, fd, fd_list)do { if (((fd)->fd_list.le_next = (&fuse_d_list)->lh_first
) != ((void *)0)) (&fuse_d_list)->lh_first->fd_list
.le_prev = &(fd)->fd_list.le_next; (&fuse_d_list)->
lh_first = (fd); (fd)->fd_list.le_prev = &(&fuse_d_list
)->lh_first; } while (0)
;
226
227 stat_opened_fusedev++;
228 return (0);
229}
230
231int
232fuseclose(dev_t dev, int flags, int fmt, struct proc *p)
233{
234 struct fuse_d *fd;
235 int error;
236
237 fd = fuse_lookup(minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
238 if (fd == NULL((void *)0))
239 return (EINVAL22);
240
241 if (fd->fd_fmp) {
242 printf("fuse: device close without umount\n");
243 fd->fd_fmp->sess_init = 0;
244 fuse_device_cleanup(dev);
245 if ((vfs_busy(fd->fd_fmp->mp, VB_WRITE0x02 | VB_NOWAIT0x04)) != 0)
246 goto end;
247 error = dounmount(fd->fd_fmp->mp, MNT_FORCE0x00080000, p);
248 if (error)
249 printf("fuse: unmount failed with error %d\n", error);
250 fd->fd_fmp = NULL((void *)0);
251 }
252
253end:
254 LIST_REMOVE(fd, fd_list)do { if ((fd)->fd_list.le_next != ((void *)0)) (fd)->fd_list
.le_next->fd_list.le_prev = (fd)->fd_list.le_prev; *(fd
)->fd_list.le_prev = (fd)->fd_list.le_next; ((fd)->fd_list
.le_prev) = ((void *)-1); ((fd)->fd_list.le_next) = ((void
*)-1); } while (0)
;
255 free(fd, M_DEVBUF2, sizeof(*fd));
256 stat_opened_fusedev--;
257 return (0);
258}
259
260/*
261 * FIOCGETFBDAT Get fusebuf data from kernel to user
262 * FIOCSETFBDAT Set fusebuf data from user to kernel
263 */
264int
265fuseioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
266{
267 struct fb_ioctl_xch *ioexch;
268 struct fusebuf *lastfbuf;
269 struct fusebuf *fbuf;
270 struct fuse_d *fd;
271 int error = 0;
272
273 fd = fuse_lookup(minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
274 if (fd == NULL((void *)0))
275 return (ENXIO6);
276
277 switch (cmd) {
278 case FIOCGETFBDAT((unsigned long)0x80000000 | ((sizeof(struct fb_ioctl_xch) &
0x1fff) << 16) | ((('F')) << 8) | ((0)))
:
279 ioexch = (struct fb_ioctl_xch *)addr;
280
281 /* Looking for uuid in fd_fbufs_in */
282 SIMPLEQ_FOREACH(fbuf, &fd->fd_fbufs_in, fb_next)for((fbuf) = ((&fd->fd_fbufs_in)->sqh_first); (fbuf
) != ((void *)0); (fbuf) = ((fbuf)->fb_hdr.fh_next.sqe_next
))
{
283 if (fbuf->fb_uuidfb_hdr.fh_uuid == ioexch->fbxch_uuid)
284 break;
285
286 lastfbuf = fbuf;
287 }
288 if (fbuf == NULL((void *)0)) {
289 printf("fuse: Cannot find fusebuf\n");
290 return (EINVAL22);
291 }
292
293 /* Remove the fbuf from fd_fbufs_in */
294 if (fbuf == SIMPLEQ_FIRST(&fd->fd_fbufs_in)((&fd->fd_fbufs_in)->sqh_first))
295 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_in, fb_next)do { if (((&fd->fd_fbufs_in)->sqh_first = (&fd->
fd_fbufs_in)->sqh_first->fb_hdr.fh_next.sqe_next) == ((
void *)0)) (&fd->fd_fbufs_in)->sqh_last = &(&
fd->fd_fbufs_in)->sqh_first; } while (0)
;
296 else
297 SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_in, lastfbuf,do { if (((lastfbuf)->fb_hdr.fh_next.sqe_next = (lastfbuf)
->fb_hdr.fh_next.sqe_next->fb_hdr.fh_next.sqe_next) == (
(void *)0)) (&fd->fd_fbufs_in)->sqh_last = &(lastfbuf
)->fb_hdr.fh_next.sqe_next; } while (0)
298 fb_next)do { if (((lastfbuf)->fb_hdr.fh_next.sqe_next = (lastfbuf)
->fb_hdr.fh_next.sqe_next->fb_hdr.fh_next.sqe_next) == (
(void *)0)) (&fd->fd_fbufs_in)->sqh_last = &(lastfbuf
)->fb_hdr.fh_next.sqe_next; } while (0)
;
299 stat_fbufs_in--;
300
301 /* Do not handle fbufs with bad len */
302 if (fbuf->fb_lenfb_hdr.fh_len != ioexch->fbxch_len) {
303 printf("fuse: Bad fusebuf len\n");
304 return (EINVAL22);
305 }
306
307 /* Update the userland fbuf */
308 error = copyout(fbuf->fb_dat, ioexch->fbxch_data,
309 ioexch->fbxch_len);
310 if (error) {
311 printf("fuse: cannot copyout\n");
312 return (error);
313 }
314
315#ifdef FUSE_DEBUG
316 fuse_dump_buff(fbuf->fb_dat, fbuf->fb_lenfb_hdr.fh_len);
317#endif
318
319 /* Adding fbuf in fd_fbufs_wait */
320 free(fbuf->fb_dat, M_FUSEFS65, fbuf->fb_lenfb_hdr.fh_len);
321 fbuf->fb_dat = NULL((void *)0);
322 SIMPLEQ_INSERT_TAIL(&fd->fd_fbufs_wait, fbuf, fb_next)do { (fbuf)->fb_hdr.fh_next.sqe_next = ((void *)0); *(&
fd->fd_fbufs_wait)->sqh_last = (fbuf); (&fd->fd_fbufs_wait
)->sqh_last = &(fbuf)->fb_hdr.fh_next.sqe_next; } while
(0)
;
323 stat_fbufs_wait++;
324 break;
325
326 case FIOCSETFBDAT((unsigned long)0x80000000 | ((sizeof(struct fb_ioctl_xch) &
0x1fff) << 16) | ((('F')) << 8) | ((1)))
:
327 DPRINTF("SET BUFFER\n");
328 ioexch = (struct fb_ioctl_xch *)addr;
329
330 /* looking for uuid in fd_fbufs_wait */
331 SIMPLEQ_FOREACH(fbuf, &fd->fd_fbufs_wait, fb_next)for((fbuf) = ((&fd->fd_fbufs_wait)->sqh_first); (fbuf
) != ((void *)0); (fbuf) = ((fbuf)->fb_hdr.fh_next.sqe_next
))
{
332 if (fbuf->fb_uuidfb_hdr.fh_uuid == ioexch->fbxch_uuid)
333 break;
334
335 lastfbuf = fbuf;
336 }
337 if (fbuf == NULL((void *)0)) {
338 printf("fuse: Cannot find fusebuf\n");
339 return (EINVAL22);
340 }
341
342 /* Do not handle fbufs with bad len */
343 if (fbuf->fb_lenfb_hdr.fh_len != ioexch->fbxch_len) {
344 printf("fuse: Bad fusebuf size\n");
345 return (EINVAL22);
346 }
347
348 /* fetching data from userland */
349 fbuf->fb_dat = malloc(ioexch->fbxch_len, M_FUSEFS65,
350 M_WAITOK0x0001 | M_ZERO0x0008);
351 error = copyin(ioexch->fbxch_data, fbuf->fb_dat,
352 ioexch->fbxch_len);
353 if (error) {
354 printf("fuse: Cannot copyin\n");
355 free(fbuf->fb_dat, M_FUSEFS65, fbuf->fb_lenfb_hdr.fh_len);
356 fbuf->fb_dat = NULL((void *)0);
357 return (error);
358 }
359
360#ifdef FUSE_DEBUG
361 fuse_dump_buff(fbuf->fb_dat, fbuf->fb_lenfb_hdr.fh_len);
362#endif
363
364 /* Remove fbuf from fd_fbufs_wait */
365 if (fbuf == SIMPLEQ_FIRST(&fd->fd_fbufs_wait)((&fd->fd_fbufs_wait)->sqh_first))
366 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_wait, fb_next)do { if (((&fd->fd_fbufs_wait)->sqh_first = (&fd
->fd_fbufs_wait)->sqh_first->fb_hdr.fh_next.sqe_next
) == ((void *)0)) (&fd->fd_fbufs_wait)->sqh_last = &
(&fd->fd_fbufs_wait)->sqh_first; } while (0)
;
367 else
368 SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_wait, lastfbuf,do { if (((lastfbuf)->fb_hdr.fh_next.sqe_next = (lastfbuf)
->fb_hdr.fh_next.sqe_next->fb_hdr.fh_next.sqe_next) == (
(void *)0)) (&fd->fd_fbufs_wait)->sqh_last = &(
lastfbuf)->fb_hdr.fh_next.sqe_next; } while (0)
369 fb_next)do { if (((lastfbuf)->fb_hdr.fh_next.sqe_next = (lastfbuf)
->fb_hdr.fh_next.sqe_next->fb_hdr.fh_next.sqe_next) == (
(void *)0)) (&fd->fd_fbufs_wait)->sqh_last = &(
lastfbuf)->fb_hdr.fh_next.sqe_next; } while (0)
;
370 stat_fbufs_wait--;
371 wakeup(fbuf);
372 break;
373 default:
374 error = EINVAL22;
375 }
376
377 return (error);
378}
379
380int
381fuseread(dev_t dev, struct uio *uio, int ioflag)
382{
383 struct fuse_d *fd;
384 struct fusebuf *fbuf;
385 struct fb_hdr hdr;
386 void *tmpaddr;
387 int error = 0;
388
389 fd = fuse_lookup(minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
390 if (fd == NULL((void *)0))
391 return (ENXIO6);
392
393 if (SIMPLEQ_EMPTY(&fd->fd_fbufs_in)(((&fd->fd_fbufs_in)->sqh_first) == ((void *)0))) {
394 if (ioflag & O_NONBLOCK0x0004)
395 return (EAGAIN35);
396
397 goto end;
398 }
399 fbuf = SIMPLEQ_FIRST(&fd->fd_fbufs_in)((&fd->fd_fbufs_in)->sqh_first);
400
401 /* We get the whole fusebuf or nothing */
402 if (uio->uio_resid != FUSEBUFSIZE(sizeof(struct fusebuf)))
403 return (EINVAL22);
404
405 /* Do not send kernel pointers */
406 memcpy(&hdr.fh_next, &fbuf->fb_next, sizeof(fbuf->fb_next))__builtin_memcpy((&hdr.fh_next), (&fbuf->fb_hdr.fh_next
), (sizeof(fbuf->fb_hdr.fh_next)))
;
407 memset(&fbuf->fb_next, 0, sizeof(fbuf->fb_next))__builtin_memset((&fbuf->fb_hdr.fh_next), (0), (sizeof
(fbuf->fb_hdr.fh_next)))
;
408 tmpaddr = fbuf->fb_dat;
409 fbuf->fb_dat = NULL((void *)0);
410 error = uiomove(fbuf, FUSEBUFSIZE(sizeof(struct fusebuf)), uio);
411 if (error)
412 goto end;
413
414#ifdef FUSE_DEBUG
415 fuse_dump_buff((char *)fbuf, FUSEBUFSIZE(sizeof(struct fusebuf)));
416#endif
417 /* Restore kernel pointers */
418 memcpy(&fbuf->fb_next, &hdr.fh_next, sizeof(fbuf->fb_next))__builtin_memcpy((&fbuf->fb_hdr.fh_next), (&hdr.fh_next
), (sizeof(fbuf->fb_hdr.fh_next)))
;
419 fbuf->fb_dat = tmpaddr;
420
421 /* Remove the fbuf if it does not contains data */
422 if (fbuf->fb_lenfb_hdr.fh_len == 0) {
423 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_in, fb_next)do { if (((&fd->fd_fbufs_in)->sqh_first = (&fd->
fd_fbufs_in)->sqh_first->fb_hdr.fh_next.sqe_next) == ((
void *)0)) (&fd->fd_fbufs_in)->sqh_last = &(&
fd->fd_fbufs_in)->sqh_first; } while (0)
;
424 stat_fbufs_in--;
425 SIMPLEQ_INSERT_TAIL(&fd->fd_fbufs_wait, fbuf, fb_next)do { (fbuf)->fb_hdr.fh_next.sqe_next = ((void *)0); *(&
fd->fd_fbufs_wait)->sqh_last = (fbuf); (&fd->fd_fbufs_wait
)->sqh_last = &(fbuf)->fb_hdr.fh_next.sqe_next; } while
(0)
;
426 stat_fbufs_wait++;
427 }
428
429end:
430 return (error);
431}
432
433int
434fusewrite(dev_t dev, struct uio *uio, int ioflag)
435{
436 struct fusebuf *lastfbuf;
437 struct fuse_d *fd;
438 struct fusebuf *fbuf;
439 struct fb_hdr hdr;
440 int error = 0;
441
442 fd = fuse_lookup(minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
443 if (fd == NULL((void *)0))
444 return (ENXIO6);
445
446 /* We get the whole fusebuf or nothing */
447 if (uio->uio_resid != FUSEBUFSIZE(sizeof(struct fusebuf)))
448 return (EINVAL22);
449
450 if ((error = uiomove(&hdr, sizeof(hdr), uio)) != 0)
451 return (error);
452
453 /* looking for uuid in fd_fbufs_wait */
454 SIMPLEQ_FOREACH(fbuf, &fd->fd_fbufs_wait, fb_next)for((fbuf) = ((&fd->fd_fbufs_wait)->sqh_first); (fbuf
) != ((void *)0); (fbuf) = ((fbuf)->fb_hdr.fh_next.sqe_next
))
{
455 if (fbuf->fb_uuidfb_hdr.fh_uuid == hdr.fh_uuid)
456 break;
457
458 lastfbuf = fbuf;
459 }
460 if (fbuf == NULL((void *)0))
461 return (EINVAL22);
462
463 /* Update fb_hdr */
464 fbuf->fb_lenfb_hdr.fh_len = hdr.fh_len;
465 fbuf->fb_errfb_hdr.fh_err = hdr.fh_err;
466 fbuf->fb_inofb_hdr.fh_ino = hdr.fh_ino;
467
468 /* Check for corrupted fbufs */
469 if ((fbuf->fb_lenfb_hdr.fh_len && fbuf->fb_errfb_hdr.fh_err) ||
470 SIMPLEQ_EMPTY(&fd->fd_fbufs_wait)(((&fd->fd_fbufs_wait)->sqh_first) == ((void *)0))) {
471 printf("fuse: dropping corrupted fusebuf\n");
472 error = EINVAL22;
473 goto end;
474 }
475
476 /* Get the missing data from the fbuf */
477 error = uiomove(&fbuf->FD, uio->uio_resid, uio);
478 if (error)
479 return error;
480 fbuf->fb_dat = NULL((void *)0);
481#ifdef FUSE_DEBUG
482 fuse_dump_buff((char *)fbuf, FUSEBUFSIZE(sizeof(struct fusebuf)));
483#endif
484
485 switch (fbuf->fb_typefb_hdr.fh_type) {
486 case FBT_INIT19:
487 fd->fd_fmp->sess_init = 1;
488 break ;
489 case FBT_DESTROY26:
490 fd->fd_fmp = NULL((void *)0);
491 break ;
492 }
493end:
494 /* Remove the fbuf if it does not contains data */
495 if (fbuf->fb_lenfb_hdr.fh_len == 0) {
496 if (fbuf == SIMPLEQ_FIRST(&fd->fd_fbufs_wait)((&fd->fd_fbufs_wait)->sqh_first))
497 SIMPLEQ_REMOVE_HEAD(&fd->fd_fbufs_wait, fb_next)do { if (((&fd->fd_fbufs_wait)->sqh_first = (&fd
->fd_fbufs_wait)->sqh_first->fb_hdr.fh_next.sqe_next
) == ((void *)0)) (&fd->fd_fbufs_wait)->sqh_last = &
(&fd->fd_fbufs_wait)->sqh_first; } while (0)
;
498 else
499 SIMPLEQ_REMOVE_AFTER(&fd->fd_fbufs_wait, lastfbuf,do { if (((lastfbuf)->fb_hdr.fh_next.sqe_next = (lastfbuf)
->fb_hdr.fh_next.sqe_next->fb_hdr.fh_next.sqe_next) == (
(void *)0)) (&fd->fd_fbufs_wait)->sqh_last = &(
lastfbuf)->fb_hdr.fh_next.sqe_next; } while (0)
500 fb_next)do { if (((lastfbuf)->fb_hdr.fh_next.sqe_next = (lastfbuf)
->fb_hdr.fh_next.sqe_next->fb_hdr.fh_next.sqe_next) == (
(void *)0)) (&fd->fd_fbufs_wait)->sqh_last = &(
lastfbuf)->fb_hdr.fh_next.sqe_next; } while (0)
;
501 stat_fbufs_wait--;
502 if (fbuf->fb_typefb_hdr.fh_type == FBT_INIT19)
503 fb_delete(fbuf);
504 else
505 wakeup(fbuf);
506 }
507
508 return (error);
509}
510
511int
512fusepoll(dev_t dev, int events, struct proc *p)
513{
514 struct fuse_d *fd;
515 int revents = 0;
516
517 fd = fuse_lookup(minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
518 if (fd == NULL((void *)0))
519 return (POLLERR0x0008);
520
521 if (events & (POLLIN0x0001 | POLLRDNORM0x0040))
522 if (!SIMPLEQ_EMPTY(&fd->fd_fbufs_in)(((&fd->fd_fbufs_in)->sqh_first) == ((void *)0)))
523 revents |= events & (POLLIN0x0001 | POLLRDNORM0x0040);
524
525 if (events & (POLLOUT0x0004 | POLLWRNORM0x0004))
526 revents |= events & (POLLOUT0x0004 | POLLWRNORM0x0004);
527
528 if (revents == 0)
529 if (events & (POLLIN0x0001 | POLLRDNORM0x0040))
530 selrecord(p, &fd->fd_rsel);
531
532 return (revents);
533}
534
535int
536fusekqfilter(dev_t dev, struct knote *kn)
537{
538 struct fuse_d *fd;
539 struct klist *klist;
540
541 fd = fuse_lookup(minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
542 if (fd == NULL((void *)0))
543 return (EINVAL22);
544
545 switch (kn->kn_filterkn_kevent.filter) {
546 case EVFILT_READ(-1):
547 klist = &fd->fd_rsel.si_note;
548 kn->kn_fop = &fuse_rd_filtops;
549 break;
550 case EVFILT_WRITE(-2):
551 return (seltrue_kqfilter(dev, kn));
552 default:
553 return (EINVAL22);
554 }
555
556 kn->kn_hook = fd;
557
558 klist_insert_locked(klist, kn);
559
560 return (0);
561}
562
563void
564filt_fuse_rdetach(struct knote *kn)
565{
566 struct fuse_d *fd = kn->kn_hook;
567 struct klist *klist = &fd->fd_rsel.si_note;
568
569 klist_remove_locked(klist, kn);
570}
571
572int
573filt_fuse_read(struct knote *kn, long hint)
574{
575 struct fuse_d *fd = kn->kn_hook;
576 int event = 0;
577
578 if (!SIMPLEQ_EMPTY(&fd->fd_fbufs_in)(((&fd->fd_fbufs_in)->sqh_first) == ((void *)0)))
579 event = 1;
580
581 return (event);
582}