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