fuse_backend_rs/api/server/
sync_io.rs

1// Copyright (C) 2021-2022 Alibaba Cloud. All rights reserved.
2// Copyright 2019 The Chromium OS Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE-BSD-3-Clause file.
5
6use std::io::{self, IoSlice, Read, Write};
7use std::mem::size_of;
8use std::sync::Arc;
9use std::time::Duration;
10use vm_memory::ByteValued;
11
12use super::{
13    MetricsHook, Server, ServerUtil, ServerVersion, SrvContext, ZcReader, ZcWriter,
14    BUFFER_HEADER_SIZE, DIRENT_PADDING, MAX_BUFFER_SIZE, MAX_REQ_PAGES, MIN_READ_BUFFER,
15};
16use crate::abi::fuse_abi::*;
17#[cfg(feature = "virtiofs")]
18use crate::abi::virtio_fs::{RemovemappingIn, RemovemappingOne, SetupmappingIn};
19use crate::api::filesystem::{
20    DirEntry, Entry, FileSystem, GetxattrReply, IoctlData, ListxattrReply,
21};
22#[cfg(feature = "fusedev")]
23use crate::transport::FuseDevWriter;
24use crate::transport::{pagesize, FsCacheReqHandler, Reader, Writer};
25use crate::{bytes_to_cstr, encode_io_error_kind, BitmapSlice, Error, Result};
26
27impl<F: FileSystem + Sync> Server<F> {
28    #[cfg(feature = "fusedev")]
29    /// Use to send notify msg to kernel fuse
30    pub fn notify_inval_entry<S: BitmapSlice>(
31        &self,
32        mut w: FuseDevWriter<'_, S>,
33        parent: u64,
34        name: &std::ffi::CStr,
35    ) -> Result<usize> {
36        let mut buffer_writer = w.split_at(0).map_err(Error::FailedToSplitWriter)?;
37        let mut entry = NotifyInvalEntryOut::default();
38        let mut header = OutHeader::default();
39        let name_with_null = name.to_bytes_with_nul();
40        header.unique = 0;
41        header.error = NotifyOpcode::InvalEntry as i32;
42        header.len = std::mem::size_of::<OutHeader>() as u32
43            + std::mem::size_of::<NotifyInvalEntryOut>() as u32
44            + name_with_null.len() as u32;
45        // the namelne don't contains the nul
46        entry.namelen = (name_with_null.len() - 1) as u32;
47        entry.parent = parent;
48
49        buffer_writer
50            .write_obj(header)
51            .map_err(Error::FailedToWrite)?;
52        buffer_writer
53            .write_obj(entry)
54            .map_err(Error::FailedToWrite)?;
55        buffer_writer
56            .write(name_with_null)
57            .map_err(Error::FailedToWrite)?;
58        buffer_writer.commit(None).map_err(Error::InvalidMessage)
59    }
60    /// Notify the kernel that an inode's data has been invalidated.
61    #[cfg(feature = "fusedev")]
62    pub fn notify_inval_inode<S: BitmapSlice>(
63        &self,
64        mut w: FuseDevWriter<'_, S>,
65        ino: u64,
66        off: u64,
67        len: u64,
68    ) -> Result<usize> {
69        let mut buffer_writer = w.split_at(0).map_err(Error::FailedToSplitWriter)?;
70        let mut header = OutHeader::default();
71        let mut inode = NotifyInvalInodeOut::default();
72
73        header.unique = 0;
74        header.error = NotifyOpcode::InvalInode as i32;
75        header.len = std::mem::size_of::<OutHeader>() as u32
76            + std::mem::size_of::<NotifyInvalInodeOut>() as u32;
77
78        inode.ino = ino;
79        inode.off = off as i64;
80        inode.len = len as i64;
81
82        buffer_writer
83            .write_obj(header)
84            .map_err(Error::FailedToWrite)?;
85        buffer_writer
86            .write_obj(inode)
87            .map_err(Error::FailedToWrite)?;
88        buffer_writer.commit(None).map_err(Error::InvalidMessage)
89    }
90    #[cfg(feature = "fusedev")]
91    /// Send a resend notification message to the kernel via FUSE. This function should be invoked as part of
92    /// the crash recovery routine. Given that FUSE initialization does not occur again during recovery,
93    /// the capability to support resend notifications may not be automatically detected. It is the responsibility
94    /// of the upper layers to verify and persist the kernel's support for this feature upon the initial FUSE setup.
95    pub fn notify_resend<S: BitmapSlice>(&self, mut w: FuseDevWriter<'_, S>) -> Result<()> {
96        let mut buffer_writer = w.split_at(0).map_err(Error::FailedToSplitWriter)?;
97        let header = {
98            OutHeader {
99                len: std::mem::size_of::<OutHeader>() as u32,
100                unique: 0,
101                error: NotifyOpcode::Resend as i32,
102            }
103        };
104        buffer_writer
105            .write_obj(header)
106            .map_err(Error::FailedToWrite)?;
107        buffer_writer.commit(None).map_err(Error::InvalidMessage)?;
108        Ok(())
109    }
110
111    /// Main entrance to handle requests from the transport layer.
112    ///
113    /// It receives Fuse requests from transport layers, parses the request according to Fuse ABI,
114    /// invokes filesystem drivers to server the requests, and eventually send back the result to
115    /// the transport layer.
116    #[allow(unused_variables)]
117    pub fn handle_message<S: BitmapSlice>(
118        &self,
119        mut r: Reader<'_, S>,
120        w: Writer<'_, S>,
121        vu_req: Option<&mut dyn FsCacheReqHandler>,
122        hook: Option<&dyn MetricsHook>,
123    ) -> Result<usize> {
124        let in_header: InHeader = r.read_obj().map_err(Error::DecodeMessage)?;
125        let mut ctx = SrvContext::<F, S>::new(in_header, r, w);
126        self.fs
127            .id_remap(&mut ctx.context)
128            .map_err(|e| Error::FailedToRemapID((ctx.context.uid, ctx.context.gid)))?;
129        if ctx.in_header.len > (MAX_BUFFER_SIZE + BUFFER_HEADER_SIZE) {
130            if in_header.opcode == Opcode::Forget as u32
131                || in_header.opcode == Opcode::BatchForget as u32
132            {
133                // Forget and batch-forget do not require reply.
134                return Err(Error::InvalidMessage(io::Error::from_raw_os_error(
135                    libc::EOVERFLOW,
136                )));
137            }
138            return ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::ENOMEM));
139        }
140
141        trace!(
142            "fuse: new req {:?}: {:?}",
143            Opcode::from(in_header.opcode),
144            in_header
145        );
146
147        if let Some(h) = hook {
148            h.collect(&in_header);
149        }
150
151        let res = match in_header.opcode {
152            x if x == Opcode::Lookup as u32 => self.lookup(ctx),
153            x if x == Opcode::Forget as u32 => self.forget(ctx), // No reply.
154            x if x == Opcode::Getattr as u32 => self.getattr(ctx),
155            x if x == Opcode::Setattr as u32 => self.setattr(ctx),
156            x if x == Opcode::Readlink as u32 => self.readlink(ctx),
157            x if x == Opcode::Symlink as u32 => self.symlink(ctx),
158            x if x == Opcode::Mknod as u32 => self.mknod(ctx),
159            x if x == Opcode::Mkdir as u32 => self.mkdir(ctx),
160            x if x == Opcode::Unlink as u32 => self.unlink(ctx),
161            x if x == Opcode::Rmdir as u32 => self.rmdir(ctx),
162            x if x == Opcode::Rename as u32 => self.rename(ctx),
163            x if x == Opcode::Link as u32 => self.link(ctx),
164            x if x == Opcode::Open as u32 => self.open(ctx),
165            x if x == Opcode::Read as u32 => self.read(ctx),
166            x if x == Opcode::Write as u32 => self.write(ctx),
167            x if x == Opcode::Statfs as u32 => self.statfs(ctx),
168            x if x == Opcode::Release as u32 => self.release(ctx),
169            x if x == Opcode::Fsync as u32 => self.fsync(ctx),
170            x if x == Opcode::Setxattr as u32 => self.setxattr(ctx),
171            x if x == Opcode::Getxattr as u32 => self.getxattr(ctx),
172            x if x == Opcode::Listxattr as u32 => self.listxattr(ctx),
173            x if x == Opcode::Removexattr as u32 => self.removexattr(ctx),
174            x if x == Opcode::Flush as u32 => self.flush(ctx),
175            x if x == Opcode::Init as u32 => self.init(ctx),
176            x if x == Opcode::Opendir as u32 => self.opendir(ctx),
177            x if x == Opcode::Readdir as u32 => self.readdir(ctx),
178            x if x == Opcode::Releasedir as u32 => self.releasedir(ctx),
179            x if x == Opcode::Fsyncdir as u32 => self.fsyncdir(ctx),
180            x if x == Opcode::Getlk as u32 => self.getlk(ctx),
181            x if x == Opcode::Setlk as u32 => self.setlk(ctx),
182            x if x == Opcode::Setlkw as u32 => self.setlkw(ctx),
183            x if x == Opcode::Access as u32 => self.access(ctx),
184            x if x == Opcode::Create as u32 => self.create(ctx),
185            x if x == Opcode::Bmap as u32 => self.bmap(ctx),
186            x if x == Opcode::Ioctl as u32 => self.ioctl(ctx),
187            x if x == Opcode::Poll as u32 => self.poll(ctx),
188            x if x == Opcode::NotifyReply as u32 => self.notify_reply(ctx),
189            x if x == Opcode::BatchForget as u32 => self.batch_forget(ctx),
190            x if x == Opcode::Fallocate as u32 => self.fallocate(ctx),
191            #[cfg(target_os = "linux")]
192            x if x == Opcode::Readdirplus as u32 => self.readdirplus(ctx),
193            #[cfg(target_os = "linux")]
194            x if x == Opcode::Rename2 as u32 => self.rename2(ctx),
195            #[cfg(target_os = "linux")]
196            x if x == Opcode::Lseek as u32 => self.lseek(ctx),
197            #[cfg(feature = "virtiofs")]
198            x if x == Opcode::SetupMapping as u32 => self.setupmapping(ctx, vu_req),
199            #[cfg(feature = "virtiofs")]
200            x if x == Opcode::RemoveMapping as u32 => self.removemapping(ctx, vu_req),
201            // Group reqeusts don't need reply together
202            x => match x {
203                x if x == Opcode::Interrupt as u32 => {
204                    self.interrupt(ctx);
205                    Ok(0)
206                }
207                x if x == Opcode::Destroy as u32 => {
208                    self.destroy(ctx);
209                    Ok(0)
210                }
211                _ => ctx.reply_error(io::Error::from_raw_os_error(libc::ENOSYS)),
212            },
213        };
214
215        // Pass `None` because current API handler's design does not allow us to catch
216        // the `out_header`. Hopefully, we can reach to `out_header` after some
217        // refactoring work someday.
218        if let Some(h) = hook {
219            h.release(None);
220        }
221
222        res
223    }
224
225    fn lookup<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
226        let buf = ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, 0)?;
227        let name = bytes_to_cstr(buf.as_ref()).map_err(|e| {
228            let _ = ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL));
229            error!("fuse: bytes to cstr error: {:?}, {:?}", buf, e);
230            e
231        })?;
232
233        #[cfg(not(feature = "fuse-t"))]
234        let version = self.vers.load();
235        let result = self.fs.lookup(ctx.context(), ctx.nodeid(), name);
236
237        match result {
238            // before ABI 7.4 inode == 0 was invalid, only ENOENT means negative dentry
239            #[cfg(not(feature = "fuse-t"))]
240            Ok(entry)
241                if version.minor < KERNEL_MINOR_VERSION_LOOKUP_NEGATIVE_ENTRY_ZERO
242                    && entry.inode == 0 =>
243            {
244                ctx.reply_error(io::Error::from_raw_os_error(libc::ENOENT))
245            }
246            #[cfg(feature = "fuse-t")]
247            Ok(entry) if entry.inode == 0 => {
248                ctx.reply_error(io::Error::from_raw_os_error(libc::ENOENT))
249            }
250            Ok(entry) => {
251                let out = EntryOut::from(entry);
252
253                ctx.reply_ok(Some(out), None)
254            }
255            Err(e) => ctx.reply_error(e),
256        }
257    }
258
259    pub(super) fn forget<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
260        let ForgetIn { nlookup } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
261
262        self.fs.forget(ctx.context(), ctx.nodeid(), nlookup);
263
264        // There is no reply for forget messages.
265        Ok(0)
266    }
267
268    fn getattr<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
269        let GetattrIn { flags, fh, .. } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
270        let handle = if (flags & GETATTR_FH) != 0 {
271            Some(fh.into())
272        } else {
273            None
274        };
275        let result = self.fs.getattr(ctx.context(), ctx.nodeid(), handle);
276
277        ctx.handle_attr_result(result)
278    }
279
280    fn setattr<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
281        let setattr_in: SetattrIn = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
282        let handle = if setattr_in.valid & FATTR_FH != 0 {
283            Some(setattr_in.fh.into())
284        } else {
285            None
286        };
287        let valid = SetattrValid::from_bits_truncate(setattr_in.valid);
288        let st: stat64 = setattr_in.into();
289        let result = self
290            .fs
291            .setattr(ctx.context(), ctx.nodeid(), st, handle, valid);
292
293        ctx.handle_attr_result(result)
294    }
295
296    pub(super) fn readlink<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
297        match self.fs.readlink(ctx.context(), ctx.nodeid()) {
298            Ok(linkname) => {
299                // We need to disambiguate the option type here even though it is `None`.
300                ctx.reply_ok(None::<u8>, Some(&linkname))
301            }
302            Err(e) => ctx.reply_error(e),
303        }
304    }
305
306    pub(super) fn symlink<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
307        let buf = ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, 0)?;
308        // The name and linkname are encoded one after another and separated by a nul character.
309        let (name, linkname) = ServerUtil::extract_two_cstrs(&buf)?;
310
311        match self.fs.symlink(ctx.context(), linkname, ctx.nodeid(), name) {
312            Ok(entry) => ctx.reply_ok(Some(EntryOut::from(entry)), None),
313            Err(e) => ctx.reply_error(e),
314        }
315    }
316
317    pub(super) fn mknod<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
318        let MknodIn {
319            mode, rdev, umask, ..
320        } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
321        let buf = ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, size_of::<MknodIn>())?;
322        let name = bytes_to_cstr(buf.as_ref()).map_err(|e| {
323            let _ = ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL));
324            error!("fuse: bytes to cstr error: {:?}, {:?}", buf, e);
325            e
326        })?;
327
328        match self
329            .fs
330            .mknod(ctx.context(), ctx.nodeid(), name, mode, rdev, umask)
331        {
332            Ok(entry) => ctx.reply_ok(Some(EntryOut::from(entry)), None),
333            Err(e) => ctx.reply_error(e),
334        }
335    }
336
337    pub(super) fn mkdir<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
338        let MkdirIn { mode, umask } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
339        let buf = ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, size_of::<MkdirIn>())?;
340        let name = bytes_to_cstr(buf.as_ref()).map_err(|e| {
341            let _ = ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL));
342            error!("fuse: bytes to cstr error: {:?}, {:?}", buf, e);
343            e
344        })?;
345
346        match self
347            .fs
348            .mkdir(ctx.context(), ctx.nodeid(), name, mode, umask)
349        {
350            Ok(entry) => ctx.reply_ok(Some(EntryOut::from(entry)), None),
351            Err(e) => ctx.reply_error(e),
352        }
353    }
354
355    pub(super) fn unlink<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
356        let buf = ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, 0)?;
357        let name = bytes_to_cstr(buf.as_ref()).map_err(|e| {
358            let _ = ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL));
359            error!("fuse: bytes to cstr error: {:?}, {:?}", buf, e);
360            e
361        })?;
362
363        match self.fs.unlink(ctx.context(), ctx.nodeid(), name) {
364            Ok(()) => ctx.reply_ok(None::<u8>, None),
365            Err(e) => ctx.reply_error(e),
366        }
367    }
368
369    pub(super) fn rmdir<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
370        let buf = ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, 0)?;
371        let name = bytes_to_cstr(buf.as_ref()).map_err(|e| {
372            let _ = ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL));
373            error!("fuse: bytes to cstr error: {:?}, {:?}", buf, e);
374            e
375        })?;
376
377        match self.fs.rmdir(ctx.context(), ctx.nodeid(), name) {
378            Ok(()) => ctx.reply_ok(None::<u8>, None),
379            Err(e) => ctx.reply_error(e),
380        }
381    }
382
383    pub(super) fn do_rename<S: BitmapSlice>(
384        &self,
385        mut ctx: SrvContext<'_, F, S>,
386        msg_size: usize,
387        newdir: u64,
388        flags: u32,
389    ) -> Result<usize> {
390        let buf = ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, msg_size)?;
391        let (oldname, newname) = ServerUtil::extract_two_cstrs(&buf)?;
392
393        match self.fs.rename(
394            ctx.context(),
395            ctx.nodeid(),
396            oldname,
397            newdir.into(),
398            newname,
399            flags,
400        ) {
401            Ok(()) => ctx.reply_ok(None::<u8>, None),
402            Err(e) => ctx.reply_error(e),
403        }
404    }
405
406    pub(super) fn rename<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
407        let RenameIn { newdir, .. } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
408
409        self.do_rename(ctx, size_of::<RenameIn>(), newdir, 0)
410    }
411
412    #[cfg(target_os = "linux")]
413    pub(super) fn rename2<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
414        let Rename2In { newdir, flags, .. } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
415
416        let flags =
417            flags & (libc::RENAME_EXCHANGE | libc::RENAME_NOREPLACE | libc::RENAME_WHITEOUT);
418
419        self.do_rename(ctx, size_of::<Rename2In>(), newdir, flags)
420    }
421
422    pub(super) fn link<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
423        let LinkIn { oldnodeid } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
424        let buf = ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, size_of::<LinkIn>())?;
425        let name = bytes_to_cstr(buf.as_ref()).map_err(|e| {
426            let _ = ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL));
427            error!("fuse: bytes to cstr error: {:?}, {:?}", buf, e);
428            e
429        })?;
430
431        match self
432            .fs
433            .link(ctx.context(), oldnodeid.into(), ctx.nodeid(), name)
434        {
435            Ok(entry) => ctx.reply_ok(Some(EntryOut::from(entry)), None),
436            Err(e) => ctx.reply_error(e),
437        }
438    }
439
440    fn open<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
441        let OpenIn { flags, fuse_flags } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
442
443        match self.fs.open(ctx.context(), ctx.nodeid(), flags, fuse_flags) {
444            Ok((handle, opts, passthrough)) => {
445                let out = OpenOut {
446                    fh: handle.map(Into::into).unwrap_or(0),
447                    open_flags: opts.bits(),
448                    passthrough: passthrough.unwrap_or_default(),
449                };
450
451                ctx.reply_ok(Some(out), None)
452            }
453            Err(e) => ctx.reply_error(e),
454        }
455    }
456
457    fn read<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
458        let ReadIn {
459            fh,
460            offset,
461            size,
462            read_flags,
463            lock_owner,
464            flags,
465            ..
466        } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
467
468        let owner = if read_flags & READ_LOCKOWNER != 0 {
469            Some(lock_owner)
470        } else {
471            None
472        };
473
474        // Split the writer into 2 pieces: one for the `OutHeader` and the rest for the data.
475        let w2 = match ctx.w.split_at(size_of::<OutHeader>()) {
476            Ok(v) => v,
477            Err(_e) => return Err(Error::InvalidHeaderLength),
478        };
479        let mut data_writer = ZcWriter(w2);
480
481        match self.fs.read(
482            ctx.context(),
483            ctx.nodeid(),
484            fh.into(),
485            &mut data_writer,
486            size,
487            offset,
488            owner,
489            flags,
490        ) {
491            Ok(count) => {
492                // Don't use `reply_ok` because we need to set a custom size length for the
493                // header.
494                let out = OutHeader {
495                    len: (size_of::<OutHeader>() + count) as u32,
496                    error: 0,
497                    unique: ctx.unique(),
498                };
499
500                ctx.w
501                    .write_all(out.as_slice())
502                    .map_err(Error::EncodeMessage)?;
503                ctx.w
504                    .commit(Some(&data_writer.0))
505                    .map_err(Error::EncodeMessage)?;
506                Ok(out.len as usize)
507            }
508            Err(e) => ctx.reply_error(e),
509        }
510    }
511
512    fn write<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
513        let WriteIn {
514            fh,
515            offset,
516            size,
517            fuse_flags,
518            lock_owner,
519            flags,
520            ..
521        } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
522
523        let owner = if fuse_flags & WRITE_LOCKOWNER != 0 {
524            Some(lock_owner)
525        } else {
526            None
527        };
528
529        let delayed_write = fuse_flags & WRITE_CACHE != 0;
530
531        let mut data_reader = ZcReader(ctx.take_reader());
532
533        match self.fs.write(
534            ctx.context(),
535            ctx.nodeid(),
536            fh.into(),
537            &mut data_reader,
538            size,
539            offset,
540            owner,
541            delayed_write,
542            flags,
543            fuse_flags,
544        ) {
545            Ok(count) => {
546                let out = WriteOut {
547                    size: count as u32,
548                    ..Default::default()
549                };
550
551                ctx.reply_ok(Some(out), None)
552            }
553            Err(e) => ctx.reply_error(e),
554        }
555    }
556
557    pub(super) fn statfs<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
558        match self.fs.statfs(ctx.context(), ctx.nodeid()) {
559            Ok(st) => ctx.reply_ok(Some(Kstatfs::from(st)), None),
560            Err(e) => ctx.reply_error(e),
561        }
562    }
563
564    pub(super) fn release<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
565        let ReleaseIn {
566            fh,
567            flags,
568            release_flags,
569            lock_owner,
570        } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
571
572        let flush = release_flags & RELEASE_FLUSH != 0;
573        let flock_release = release_flags & RELEASE_FLOCK_UNLOCK != 0;
574        let lock_owner = if flush || flock_release {
575            Some(lock_owner)
576        } else {
577            None
578        };
579
580        match self.fs.release(
581            ctx.context(),
582            ctx.nodeid(),
583            flags,
584            fh.into(),
585            flush,
586            flock_release,
587            lock_owner,
588        ) {
589            Ok(()) => ctx.reply_ok(None::<u8>, None),
590            Err(e) => ctx.reply_error(e),
591        }
592    }
593
594    fn fsync<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
595        let FsyncIn {
596            fh, fsync_flags, ..
597        } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
598        let datasync = fsync_flags & 0x1 != 0;
599
600        match self
601            .fs
602            .fsync(ctx.context(), ctx.nodeid(), datasync, fh.into())
603        {
604            Ok(()) => ctx.reply_ok(None::<u8>, None),
605            Err(e) => ctx.reply_error(e),
606        }
607    }
608
609    pub(super) fn setxattr<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
610        let SetxattrIn { size, flags } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
611        let buf =
612            ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, size_of::<SetxattrIn>())?;
613
614        // The name and value and encoded one after another and separated by a '\0' character.
615        let split_pos = buf
616            .iter()
617            .position(|c| *c == b'\0')
618            .map(|p| p + 1)
619            .ok_or(Error::MissingParameter)?;
620        let (name, value) = buf.split_at(split_pos);
621
622        if size != value.len() as u32 {
623            return Err(Error::InvalidXattrSize((size, value.len())));
624        }
625        let name = bytes_to_cstr(name).map_err(|e| {
626            let _ = ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL));
627            error!("fuse: bytes to cstr error: {:?}, {:?}", buf, e);
628            e
629        })?;
630
631        match self
632            .fs
633            .setxattr(ctx.context(), ctx.nodeid(), name, value, flags)
634        {
635            Ok(()) => ctx.reply_ok(None::<u8>, None),
636            Err(e) => ctx.reply_error(e),
637        }
638    }
639
640    pub(super) fn getxattr<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
641        let GetxattrIn { size, .. } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
642
643        let buf =
644            ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, size_of::<GetxattrIn>())?;
645        let name = bytes_to_cstr(buf.as_ref()).map_err(|e| {
646            let _ = ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL));
647            error!("fuse: bytes to cstr error: {:?}, {:?}", buf, e);
648            e
649        })?;
650
651        match self.fs.getxattr(ctx.context(), ctx.nodeid(), name, size) {
652            Ok(GetxattrReply::Value(val)) => ctx.reply_ok(None::<u8>, Some(&val)),
653            Ok(GetxattrReply::Count(count)) => {
654                let out = GetxattrOut {
655                    size: count,
656                    ..Default::default()
657                };
658
659                ctx.reply_ok(Some(out), None)
660            }
661            Err(e) => ctx.reply_error(e),
662        }
663    }
664
665    pub(super) fn listxattr<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
666        let GetxattrIn { size, .. } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
667
668        match self.fs.listxattr(ctx.context(), ctx.nodeid(), size) {
669            Ok(ListxattrReply::Names(val)) => ctx.reply_ok(None::<u8>, Some(&val)),
670            Ok(ListxattrReply::Count(count)) => {
671                let out = GetxattrOut {
672                    size: count,
673                    ..Default::default()
674                };
675
676                ctx.reply_ok(Some(out), None)
677            }
678            Err(e) => ctx.reply_error(e),
679        }
680    }
681
682    pub(super) fn removexattr<S: BitmapSlice>(
683        &self,
684        mut ctx: SrvContext<'_, F, S>,
685    ) -> Result<usize> {
686        let buf = ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, 0)?;
687        let name = bytes_to_cstr(buf.as_ref()).map_err(|e| {
688            let _ = ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL));
689            error!("fuse: bytes to cstr error: {:?}, {:?}", buf, e);
690            e
691        })?;
692
693        match self.fs.removexattr(ctx.context(), ctx.nodeid(), name) {
694            Ok(()) => ctx.reply_ok(None::<u8>, None),
695            Err(e) => ctx.reply_error(e),
696        }
697    }
698
699    pub(super) fn flush<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
700        let FlushIn { fh, lock_owner, .. } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
701
702        match self
703            .fs
704            .flush(ctx.context(), ctx.nodeid(), fh.into(), lock_owner)
705        {
706            Ok(()) => ctx.reply_ok(None::<u8>, None),
707            Err(e) => ctx.reply_error(e),
708        }
709    }
710
711    pub(super) fn init<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
712        let InitIn {
713            major,
714            minor,
715            max_readahead,
716            flags,
717        } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
718
719        if major < KERNEL_VERSION {
720            error!("Unsupported fuse protocol version: {}.{}", major, minor);
721            return ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EPROTO));
722        }
723
724        if major > KERNEL_VERSION {
725            // Wait for the kernel to reply back with a 7.X version.
726            let out = InitOut {
727                major: KERNEL_VERSION,
728                minor: KERNEL_MINOR_VERSION,
729                ..Default::default()
730            };
731
732            return ctx.reply_ok(Some(out), None);
733        }
734
735        #[cfg(target_os = "macos")]
736        let flags_u64 = flags as u64;
737        #[cfg(target_os = "linux")]
738        let mut flags_u64 = flags as u64;
739        #[cfg(target_os = "linux")]
740        if flags_u64 & FsOptions::INIT_EXT.bits() != 0 {
741            let InitIn2 { flags2, unused: _ } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
742            flags_u64 |= (flags2 as u64) << 32;
743        }
744        let capable = FsOptions::from_bits_truncate(flags_u64);
745
746        match self.fs.init(capable) {
747            Ok(want) => {
748                let enabled = capable & want;
749                info!(
750                    "FUSE INIT major {} minor {}\n in_opts: {:?}\nout_opts: {:?}",
751                    major, minor, capable, enabled
752                );
753
754                let readahead = if cfg!(target_os = "macos") {
755                    0
756                } else {
757                    max_readahead
758                };
759
760                let enabled_flags = enabled.bits();
761                let mut out = InitOut {
762                    major: KERNEL_VERSION,
763                    minor: KERNEL_MINOR_VERSION,
764                    max_readahead: readahead,
765                    flags: enabled_flags as u32,
766                    max_background: u16::MAX,
767                    congestion_threshold: (u16::MAX / 4) * 3,
768                    max_write: MIN_READ_BUFFER - BUFFER_HEADER_SIZE,
769                    time_gran: 1, // nanoseconds
770                    flags2: (enabled_flags >> 32) as u32,
771                    ..Default::default()
772                };
773                if enabled.contains(FsOptions::BIG_WRITES) {
774                    out.max_write = MAX_REQ_PAGES as u32 * pagesize() as u32;
775                }
776                #[cfg(target_os = "linux")]
777                if enabled.contains(FsOptions::MAX_PAGES) {
778                    out.max_pages = MAX_REQ_PAGES;
779                    out.max_write = MAX_REQ_PAGES as u32 * pagesize() as u32; // 1MB
780                }
781                let vers = ServerVersion { major, minor };
782                self.vers.store(Arc::new(vers));
783                if minor < KERNEL_MINOR_VERSION_INIT_OUT_SIZE {
784                    ctx.reply_ok(
785                        Some(
786                            *<[u8; FUSE_COMPAT_INIT_OUT_SIZE]>::from_slice(
787                                out.as_slice().split_at(FUSE_COMPAT_INIT_OUT_SIZE).0,
788                            )
789                            .unwrap(),
790                        ),
791                        None,
792                    )
793                } else if minor < KERNEL_MINOR_VERSION_INIT_22_OUT_SIZE {
794                    ctx.reply_ok(
795                        Some(
796                            *<[u8; FUSE_COMPAT_22_INIT_OUT_SIZE]>::from_slice(
797                                out.as_slice().split_at(FUSE_COMPAT_22_INIT_OUT_SIZE).0,
798                            )
799                            .unwrap(),
800                        ),
801                        None,
802                    )
803                } else {
804                    ctx.reply_ok(Some(out), None)
805                }
806            }
807            Err(e) => ctx.reply_error(e),
808        }
809    }
810
811    pub(super) fn opendir<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
812        let OpenIn { flags, .. } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
813
814        match self.fs.opendir(ctx.context(), ctx.nodeid(), flags) {
815            Ok((handle, opts)) => {
816                let out = OpenOut {
817                    fh: handle.map(Into::into).unwrap_or(0),
818                    open_flags: opts.bits(),
819                    ..Default::default()
820                };
821
822                ctx.reply_ok(Some(out), None)
823            }
824            Err(e) => ctx.reply_error(e),
825        }
826    }
827
828    fn do_readdir<S: BitmapSlice>(
829        &self,
830        mut ctx: SrvContext<'_, F, S>,
831        plus: bool,
832    ) -> Result<usize> {
833        let ReadIn {
834            fh, offset, size, ..
835        } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
836
837        let available_bytes = ctx.w.available_bytes();
838        if available_bytes < size as usize {
839            return ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::ENOMEM));
840        }
841
842        // Skip over enough bytes for the header.
843        let mut cursor = match ctx.w.split_at(size_of::<OutHeader>()) {
844            Ok(v) => v,
845            Err(_e) => return Err(Error::InvalidHeaderLength),
846        };
847
848        let res = if plus {
849            self.fs.readdirplus(
850                ctx.context(),
851                ctx.nodeid(),
852                fh.into(),
853                size,
854                offset,
855                &mut |d, e| add_dirent(&mut cursor, size, d, Some(e)),
856            )
857        } else {
858            self.fs.readdir(
859                ctx.context(),
860                ctx.nodeid(),
861                fh.into(),
862                size,
863                offset,
864                &mut |d| add_dirent(&mut cursor, size, d, None),
865            )
866        };
867
868        if let Err(e) = res {
869            ctx.reply_error_explicit(e)
870        } else {
871            // Don't use `reply_ok` because we need to set a custom size length for the
872            // header.
873            let out = OutHeader {
874                len: (size_of::<OutHeader>() + cursor.bytes_written()) as u32,
875                error: 0,
876                unique: ctx.unique(),
877            };
878
879            ctx.w
880                .write_all(out.as_slice())
881                .map_err(Error::EncodeMessage)?;
882            ctx.w.commit(Some(&cursor)).map_err(Error::EncodeMessage)?;
883            Ok(out.len as usize)
884        }
885    }
886
887    pub(super) fn readdir<S: BitmapSlice>(&self, ctx: SrvContext<'_, F, S>) -> Result<usize> {
888        self.do_readdir(ctx, false)
889    }
890
891    #[cfg(target_os = "linux")]
892    pub(super) fn readdirplus<S: BitmapSlice>(&self, ctx: SrvContext<'_, F, S>) -> Result<usize> {
893        self.do_readdir(ctx, true)
894    }
895
896    pub(super) fn releasedir<S: BitmapSlice>(
897        &self,
898        mut ctx: SrvContext<'_, F, S>,
899    ) -> Result<usize> {
900        let ReleaseIn { fh, flags, .. } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
901
902        match self
903            .fs
904            .releasedir(ctx.context(), ctx.nodeid(), flags, fh.into())
905        {
906            Ok(()) => ctx.reply_ok(None::<u8>, None),
907            Err(e) => ctx.reply_error(e),
908        }
909    }
910
911    fn fsyncdir<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
912        let FsyncIn {
913            fh, fsync_flags, ..
914        } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
915        let datasync = fsync_flags & 0x1 != 0;
916
917        match self
918            .fs
919            .fsyncdir(ctx.context(), ctx.nodeid(), datasync, fh.into())
920        {
921            Ok(()) => ctx.reply_ok(None::<u8>, None),
922            Err(e) => ctx.reply_error(e),
923        }
924    }
925
926    pub(super) fn getlk<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
927        let LkIn {
928            fh,
929            owner,
930            lk,
931            lk_flags,
932            ..
933        } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
934        match self.fs.getlk(
935            ctx.context(),
936            ctx.nodeid(),
937            fh.into(),
938            owner,
939            lk.into(),
940            lk_flags,
941        ) {
942            Ok(l) => ctx.reply_ok(Some(LkOut { lk: l.into() }), None),
943            Err(e) => ctx.reply_error(e),
944        }
945    }
946
947    pub(super) fn setlk<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
948        let LkIn {
949            fh,
950            owner,
951            lk,
952            lk_flags,
953            ..
954        } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
955        match self.fs.setlk(
956            ctx.context(),
957            ctx.nodeid(),
958            fh.into(),
959            owner,
960            lk.into(),
961            lk_flags,
962        ) {
963            Ok(()) => ctx.reply_ok(None::<u8>, None),
964            Err(e) => ctx.reply_error(e),
965        }
966    }
967
968    pub(super) fn setlkw<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
969        let LkIn {
970            fh,
971            owner,
972            lk,
973            lk_flags,
974            ..
975        } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
976        match self.fs.setlk(
977            ctx.context(),
978            ctx.nodeid(),
979            fh.into(),
980            owner,
981            lk.into(),
982            lk_flags,
983        ) {
984            Ok(()) => ctx.reply_ok(None::<u8>, None),
985            Err(e) => ctx.reply_error(e),
986        }
987    }
988
989    pub(super) fn access<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
990        let AccessIn { mask, .. } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
991
992        match self.fs.access(ctx.context(), ctx.nodeid(), mask) {
993            Ok(()) => ctx.reply_ok(None::<u8>, None),
994            Err(e) => ctx.reply_error(e),
995        }
996    }
997
998    fn create<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
999        let args: CreateIn = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
1000        let buf = ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, size_of::<CreateIn>())?;
1001        let name = bytes_to_cstr(buf.as_ref()).map_err(|e| {
1002            let _ = ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL));
1003            error!("fuse: bytes to cstr error: {:?}, {:?}", buf, e);
1004            e
1005        })?;
1006
1007        match self.fs.create(ctx.context(), ctx.nodeid(), name, args) {
1008            Ok((entry, handle, opts, passthrough)) => {
1009                let entry_out = EntryOut {
1010                    nodeid: entry.inode,
1011                    generation: entry.generation,
1012                    entry_valid: entry.entry_timeout.as_secs(),
1013                    attr_valid: entry.attr_timeout.as_secs(),
1014                    entry_valid_nsec: entry.entry_timeout.subsec_nanos(),
1015                    attr_valid_nsec: entry.attr_timeout.subsec_nanos(),
1016                    attr: entry.attr.into(),
1017                };
1018
1019                let open_out = OpenOut {
1020                    fh: handle.map(Into::into).unwrap_or(0),
1021                    open_flags: opts.bits(),
1022                    passthrough: passthrough.unwrap_or_default(),
1023                };
1024
1025                // Kind of a hack to write both structs.
1026                ctx.reply_ok(Some(entry_out), Some(open_out.as_slice()))
1027            }
1028            Err(e) => ctx.reply_error(e),
1029        }
1030    }
1031
1032    pub(super) fn interrupt<S: BitmapSlice>(&self, _ctx: SrvContext<'_, F, S>) {}
1033
1034    pub(super) fn bmap<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
1035        let BmapIn {
1036            block, blocksize, ..
1037        } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
1038
1039        match self.fs.bmap(ctx.context(), ctx.nodeid(), block, blocksize) {
1040            Ok(block) => ctx.reply_ok(Some(BmapOut { block }), None),
1041            Err(e) => ctx.reply_error(e),
1042        }
1043    }
1044
1045    pub(super) fn destroy<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) {
1046        self.fs.destroy();
1047        if let Err(e) = ctx.reply_ok(None::<u8>, None) {
1048            warn!("fuse channel reply destroy failed {:?}", e);
1049        }
1050    }
1051
1052    pub(super) fn ioctl<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
1053        let IoctlIn {
1054            fh,
1055            flags,
1056            cmd,
1057            arg: _,
1058            in_size,
1059            out_size,
1060        } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
1061        // TODO: check fs capability of FUSE_CAP_IOCTL_DIR and return ENOTTY if unsupported.
1062        let mut buf = IoctlData {
1063            ..Default::default()
1064        };
1065        let in_size = in_size as usize;
1066        // Make sure we have enough bytes to read the ioctl in buffer.
1067        if in_size > ctx.r.available_bytes() {
1068            return ctx.reply_error(io::Error::from_raw_os_error(libc::ENOTTY));
1069        }
1070        let mut data = vec![0u8; in_size];
1071        if in_size > 0 {
1072            let size = ctx.r.read(&mut data).map_err(Error::DecodeMessage)?;
1073            if size > 0 {
1074                buf.data = Some(&data[..size]);
1075            }
1076        }
1077        match self.fs.ioctl(
1078            ctx.context(),
1079            ctx.nodeid(),
1080            fh.into(),
1081            flags,
1082            cmd,
1083            buf,
1084            out_size,
1085        ) {
1086            Ok(res) => ctx.reply_ok(
1087                Some(IoctlOut {
1088                    result: res.result,
1089                    ..Default::default()
1090                }),
1091                res.data,
1092            ),
1093            Err(e) => ctx.reply_error(e),
1094        }
1095    }
1096
1097    pub(super) fn poll<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
1098        let PollIn {
1099            fh,
1100            kh,
1101            flags,
1102            events,
1103        } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
1104
1105        match self.fs.poll(
1106            ctx.context(),
1107            ctx.nodeid(),
1108            fh.into(),
1109            kh.into(),
1110            flags,
1111            events,
1112        ) {
1113            Ok(revents) => ctx.reply_ok(
1114                Some(PollOut {
1115                    revents,
1116                    padding: 0,
1117                }),
1118                None,
1119            ),
1120            Err(e) => ctx.reply_error(e),
1121        }
1122    }
1123
1124    pub(super) fn notify_reply<S: BitmapSlice>(
1125        &self,
1126        mut ctx: SrvContext<'_, F, S>,
1127    ) -> Result<usize> {
1128        if let Err(e) = self.fs.notify_reply() {
1129            ctx.reply_error(e)
1130        } else {
1131            Ok(0)
1132        }
1133    }
1134
1135    pub(super) fn batch_forget<S: BitmapSlice>(
1136        &self,
1137        mut ctx: SrvContext<'_, F, S>,
1138    ) -> Result<usize> {
1139        let BatchForgetIn { count, .. } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
1140
1141        if let Some(size) = (count as usize).checked_mul(size_of::<ForgetOne>()) {
1142            if size
1143                > (MAX_BUFFER_SIZE + BUFFER_HEADER_SIZE
1144                    - size_of::<BatchForgetIn>() as u32
1145                    - size_of::<InHeader>() as u32) as usize
1146            {
1147                return Err(Error::InvalidMessage(io::Error::from_raw_os_error(
1148                    libc::EOVERFLOW,
1149                )));
1150            }
1151        } else {
1152            return Err(Error::InvalidMessage(io::Error::from_raw_os_error(
1153                libc::EOVERFLOW,
1154            )));
1155        }
1156
1157        let mut requests = Vec::with_capacity(count as usize);
1158        for _ in 0..count {
1159            requests.push(
1160                ctx.r
1161                    .read_obj::<ForgetOne>()
1162                    .map(|f| (f.nodeid.into(), f.nlookup))
1163                    .map_err(Error::DecodeMessage)?,
1164            );
1165        }
1166
1167        self.fs.batch_forget(ctx.context(), requests);
1168
1169        // No reply for forget messages.
1170        Ok(0)
1171    }
1172
1173    fn fallocate<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
1174        let FallocateIn {
1175            fh,
1176            offset,
1177            length,
1178            mode,
1179            ..
1180        } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
1181
1182        match self
1183            .fs
1184            .fallocate(ctx.context(), ctx.nodeid(), fh.into(), mode, offset, length)
1185        {
1186            Ok(()) => ctx.reply_ok(None::<u8>, None),
1187            Err(e) => ctx.reply_error(e),
1188        }
1189    }
1190
1191    #[cfg(target_os = "linux")]
1192    pub(super) fn lseek<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
1193        let LseekIn {
1194            fh, offset, whence, ..
1195        } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
1196
1197        match self
1198            .fs
1199            .lseek(ctx.context(), ctx.nodeid(), fh.into(), offset, whence)
1200        {
1201            Ok(offset) => {
1202                let out = LseekOut { offset };
1203
1204                ctx.reply_ok(Some(out), None)
1205            }
1206            Err(e) => ctx.reply_error(e),
1207        }
1208    }
1209}
1210
1211#[cfg(feature = "virtiofs")]
1212impl<F: FileSystem + Sync> Server<F> {
1213    pub(super) fn setupmapping<S: BitmapSlice>(
1214        &self,
1215        mut ctx: SrvContext<'_, F, S>,
1216        vu_req: Option<&mut dyn FsCacheReqHandler>,
1217    ) -> Result<usize> {
1218        if let Some(req) = vu_req {
1219            let SetupmappingIn {
1220                fh,
1221                foffset,
1222                len,
1223                flags,
1224                moffset,
1225            } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
1226
1227            match self.fs.setupmapping(
1228                ctx.context(),
1229                ctx.nodeid(),
1230                fh.into(),
1231                foffset,
1232                len,
1233                flags,
1234                moffset,
1235                req,
1236            ) {
1237                Ok(()) => ctx.reply_ok(None::<u8>, None),
1238                Err(e) => ctx.reply_error(e),
1239            }
1240        } else {
1241            ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL))
1242        }
1243    }
1244
1245    pub(super) fn removemapping<S: BitmapSlice>(
1246        &self,
1247        mut ctx: SrvContext<'_, F, S>,
1248        vu_req: Option<&mut dyn FsCacheReqHandler>,
1249    ) -> Result<usize> {
1250        if let Some(req) = vu_req {
1251            let RemovemappingIn { count } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
1252
1253            if let Some(size) = (count as usize).checked_mul(size_of::<RemovemappingOne>()) {
1254                if size > MAX_BUFFER_SIZE as usize {
1255                    return ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::ENOMEM));
1256                }
1257            } else {
1258                return ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EOVERFLOW));
1259            }
1260
1261            let mut requests = Vec::with_capacity(count as usize);
1262            for _ in 0..count {
1263                requests.push(
1264                    ctx.r
1265                        .read_obj::<RemovemappingOne>()
1266                        .map_err(Error::DecodeMessage)?,
1267                );
1268            }
1269
1270            match self
1271                .fs
1272                .removemapping(ctx.context(), ctx.nodeid(), requests, req)
1273            {
1274                Ok(()) => ctx.reply_ok(None::<u8>, None),
1275                Err(e) => ctx.reply_error(e),
1276            }
1277        } else {
1278            ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL))
1279        }
1280    }
1281}
1282
1283impl<F: FileSystem, S: BitmapSlice> SrvContext<'_, F, S> {
1284    fn reply_ok<T: ByteValued>(&mut self, out: Option<T>, data: Option<&[u8]>) -> Result<usize> {
1285        let data2 = out.as_ref().map(|v| v.as_slice()).unwrap_or(&[]);
1286        let data3 = data.unwrap_or(&[]);
1287        let len = size_of::<OutHeader>() + data2.len() + data3.len();
1288        let header = OutHeader {
1289            len: len as u32,
1290            error: 0,
1291            unique: self.unique(),
1292        };
1293        trace!("fuse: new reply {:?}", header);
1294
1295        match (data2.len(), data3.len()) {
1296            (0, 0) => self
1297                .w
1298                .write(header.as_slice())
1299                .map_err(Error::EncodeMessage)?,
1300            (0, _) => self
1301                .w
1302                .write_vectored(&[IoSlice::new(header.as_slice()), IoSlice::new(data3)])
1303                .map_err(Error::EncodeMessage)?,
1304            (_, 0) => self
1305                .w
1306                .write_vectored(&[IoSlice::new(header.as_slice()), IoSlice::new(data2)])
1307                .map_err(Error::EncodeMessage)?,
1308            (_, _) => self
1309                .w
1310                .write_vectored(&[
1311                    IoSlice::new(header.as_slice()),
1312                    IoSlice::new(data2),
1313                    IoSlice::new(data3),
1314                ])
1315                .map_err(Error::EncodeMessage)?,
1316        };
1317
1318        debug_assert_eq!(len, self.w.bytes_written());
1319        Ok(self.w.bytes_written())
1320    }
1321
1322    fn do_reply_error(&mut self, err: io::Error, explicit: bool) -> Result<usize> {
1323        let header = OutHeader {
1324            len: size_of::<OutHeader>() as u32,
1325            error: -err
1326                .raw_os_error()
1327                .unwrap_or_else(|| encode_io_error_kind(err.kind())),
1328            unique: self.unique(),
1329        };
1330
1331        if explicit || err.raw_os_error().is_none() {
1332            error!("fuse: reply error header {:?}, error {:?}", header, err);
1333        } else {
1334            trace!("fuse: reply error header {:?}, error {:?}", header, err);
1335        }
1336        self.w
1337            .write_all(header.as_slice())
1338            .map_err(Error::EncodeMessage)?;
1339
1340        // Commit header if it is buffered otherwise kernel gets nothing back.
1341        self.w
1342            .commit(None)
1343            .map(|_| {
1344                debug_assert_eq!(header.len as usize, self.w.bytes_written());
1345                self.w.bytes_written()
1346            })
1347            .map_err(Error::EncodeMessage)
1348    }
1349
1350    // reply operation error back to fuse client, don't print error message, as they are not server's
1351    // internal error, and client could deal with them.
1352    fn reply_error(&mut self, err: io::Error) -> Result<usize> {
1353        self.do_reply_error(err, false)
1354    }
1355
1356    fn reply_error_explicit(&mut self, err: io::Error) -> Result<usize> {
1357        self.do_reply_error(err, true)
1358    }
1359
1360    fn handle_attr_result(&mut self, result: io::Result<(stat64, Duration)>) -> Result<usize> {
1361        match result {
1362            Ok((st, timeout)) => {
1363                let out = AttrOut {
1364                    attr_valid: timeout.as_secs(),
1365                    attr_valid_nsec: timeout.subsec_nanos(),
1366                    dummy: 0,
1367                    attr: st.into(),
1368                };
1369                self.reply_ok(Some(out), None)
1370            }
1371            Err(e) => self.reply_error(e),
1372        }
1373    }
1374}
1375
1376fn add_dirent<S: BitmapSlice>(
1377    cursor: &mut Writer<'_, S>,
1378    max: u32,
1379    d: DirEntry,
1380    entry: Option<Entry>,
1381) -> io::Result<usize> {
1382    if d.name.len() > u32::MAX as usize {
1383        return Err(io::Error::from_raw_os_error(libc::EOVERFLOW));
1384    }
1385
1386    let dirent_len = size_of::<Dirent>()
1387        .checked_add(d.name.len())
1388        .ok_or_else(|| io::Error::from_raw_os_error(libc::EOVERFLOW))?;
1389
1390    // Directory entries must be padded to 8-byte alignment.  If adding 7 causes
1391    // an overflow then this dirent cannot be properly padded.
1392    let padded_dirent_len = dirent_len
1393        .checked_add(7)
1394        .map(|l| l & !7)
1395        .ok_or_else(|| io::Error::from_raw_os_error(libc::EOVERFLOW))?;
1396
1397    let total_len = if entry.is_some() {
1398        padded_dirent_len
1399            .checked_add(size_of::<EntryOut>())
1400            .ok_or_else(|| io::Error::from_raw_os_error(libc::EOVERFLOW))?
1401    } else {
1402        padded_dirent_len
1403    };
1404
1405    // Skip the entry if there's no enough space left.
1406    if (max as usize).saturating_sub(cursor.bytes_written()) < total_len {
1407        Ok(0)
1408    } else {
1409        if let Some(entry) = entry {
1410            cursor.write_all(EntryOut::from(entry).as_slice())?;
1411        }
1412
1413        let dirent = Dirent {
1414            ino: d.ino,
1415            off: d.offset,
1416            namelen: d.name.len() as u32,
1417            type_: d.type_,
1418        };
1419
1420        cursor.write_all(dirent.as_slice())?;
1421        cursor.write_all(d.name)?;
1422
1423        // We know that `dirent_len` <= `padded_dirent_len` due to the check above
1424        // so there's no need for checked arithmetic.
1425        let padding = padded_dirent_len - dirent_len;
1426        if padding > 0 {
1427            cursor.write_all(&DIRENT_PADDING[..padding])?;
1428        }
1429
1430        Ok(total_len)
1431    }
1432}
1433
1434#[cfg(test)]
1435mod tests {
1436
1437    #[cfg(all(feature = "fusedev", target_os = "linux"))]
1438    mod tests_fusedev {
1439        use super::super::*;
1440        use crate::passthrough::{Config, PassthroughFs};
1441        use crate::transport::FuseBuf;
1442
1443        use std::fs::File;
1444        use std::os::unix::io::AsRawFd;
1445        use vmm_sys_util::tempfile::TempFile;
1446
1447        fn prepare_srvcontext<'a>(
1448            read_buf: &'a mut [u8],
1449            write_buf: &'a mut [u8],
1450        ) -> (SrvContext<'a, PassthroughFs>, File) {
1451            let file = TempFile::new().unwrap().into_file();
1452            let reader = Reader::<()>::from_fuse_buffer(FuseBuf::new(read_buf)).unwrap();
1453            let writer = FuseDevWriter::<()>::new(file.as_raw_fd(), write_buf).unwrap();
1454            let in_header = InHeader::default();
1455            (
1456                SrvContext::<PassthroughFs>::new(in_header, reader, writer.into()),
1457                file,
1458            )
1459        }
1460
1461        #[test]
1462        fn test_server_init() {
1463            let fs = PassthroughFs::<()>::new(Config::default()).unwrap();
1464            let server = Server::new(fs);
1465
1466            let mut read_buf = [
1467                0x8u8, 0x0, 0x0, 0x0, // major = 0x0008
1468                0x0u8, 0x0, 0x0, 0x0, // minor = 0x0008
1469                0x0, 0x0, 0x0, 0x0, // max_readahead = 0x0000
1470                0x0, 0x0, 0x0, 0x0, // flags = 0x0000
1471            ];
1472            let mut write_buf = [0u8; 4096];
1473            let (ctx, _file) = prepare_srvcontext(&mut read_buf, &mut write_buf);
1474
1475            let res = server.init(ctx).unwrap();
1476            assert_eq!(res, 80);
1477
1478            let mut read_buf1 = [
1479                0x7u8, 0x0, 0x0, 0x0, // major = 0x0007
1480                0x0u8, 0x0, 0x0, 0x0, // minor = 0x0000
1481                0x0, 0x0, 0x0, 0x0, // max_readahead = 0x0000
1482                0x0, 0x0, 0x0, 0x0, // flags = 0x0000
1483            ];
1484            let mut write_buf1 = [0u8; 4096];
1485            let (ctx1, _file) = prepare_srvcontext(&mut read_buf1, &mut write_buf1);
1486
1487            let res = server.init(ctx1).unwrap();
1488            assert_eq!(res, 24);
1489        }
1490
1491        #[test]
1492        fn test_server_write() {
1493            let fs = PassthroughFs::<()>::new(Config::default()).unwrap();
1494            let server = Server::new(fs);
1495
1496            let mut read_buf = [0u8; 4096];
1497            let mut write_buf = [0u8; 4096];
1498            let (ctx, _file) = prepare_srvcontext(&mut read_buf, &mut write_buf);
1499
1500            let res = server.write(ctx).unwrap();
1501            assert_eq!(res, 16);
1502        }
1503
1504        #[test]
1505        fn test_server_read() {
1506            let fs = PassthroughFs::<()>::new(Config::default()).unwrap();
1507            let server = Server::new(fs);
1508
1509            let mut read_buf = [0u8; 4096];
1510            let mut write_buf = [0u8; 4096];
1511            let (ctx, _file) = prepare_srvcontext(&mut read_buf, &mut write_buf);
1512
1513            let res = server.read(ctx).unwrap();
1514            assert_eq!(res, 16);
1515        }
1516
1517        #[test]
1518        fn test_server_readdir() {
1519            let fs = PassthroughFs::<()>::new(Config::default()).unwrap();
1520            let server = Server::new(fs);
1521
1522            let mut read_buf = [0u8; 4096];
1523            let mut write_buf = [0u8; 4096];
1524            let (ctx, _file) = prepare_srvcontext(&mut read_buf, &mut write_buf);
1525
1526            let res = server.do_readdir(ctx, true).unwrap();
1527            assert_eq!(res, 16);
1528        }
1529
1530        #[test]
1531        fn test_server_ioctl() {
1532            let fs = PassthroughFs::<()>::new(Config::default()).unwrap();
1533            let server = Server::new(fs);
1534
1535            let mut read_buf = [0u8; 4096];
1536            let mut write_buf = [0u8; 4096];
1537            let (ctx, _file) = prepare_srvcontext(&mut read_buf, &mut write_buf);
1538
1539            let res = server.ioctl(ctx).unwrap();
1540            assert!(res > 0);
1541
1542            // construct IoctlIn with invalid in_size
1543            let mut read_buf_fail = [
1544                0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, //fh = 0
1545                0x0, 0x0, 0x0, 0x0, //flags = 0
1546                0x0, 0x0, 0x0, 0x0, //cmd = 0
1547                0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, //arg = 0
1548                0x7u8, 0x3u8, 0x0, 0x0, //in_size = 0x307
1549                0x0, 0x0, 0x0, 0x0, //out_size = 0
1550            ];
1551            let mut write_buf_fail = [0u8; 48];
1552            let (ctx_fail, _file) = prepare_srvcontext(&mut read_buf_fail, &mut write_buf_fail);
1553            let res = server.ioctl(ctx_fail).unwrap();
1554            assert!(res > 0);
1555        }
1556
1557        #[test]
1558        fn test_server_batch_forget() {
1559            let fs = PassthroughFs::<()>::new(Config::default()).unwrap();
1560            let server = Server::new(fs);
1561
1562            let mut read_buf = [0u8; 4096];
1563            let mut write_buf = [0u8; 4096];
1564            let (ctx, _file) = prepare_srvcontext(&mut read_buf, &mut write_buf);
1565            // forget should return 0 anyway
1566            assert_eq!(server.batch_forget(ctx).unwrap(), 0);
1567        }
1568
1569        #[test]
1570        fn test_server_forget() {
1571            let fs = PassthroughFs::<()>::new(Config::default()).unwrap();
1572            let server = Server::new(fs);
1573
1574            let mut read_buf = [0x1u8, 0x2u8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0];
1575            let mut write_buf = [0u8; 4096];
1576            let (ctx, _file) = prepare_srvcontext(&mut read_buf, &mut write_buf);
1577
1578            assert_eq!(server.forget(ctx).unwrap(), 0);
1579        }
1580    }
1581}