1use 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 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 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 #[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 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 #[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 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), 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 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 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 #[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 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 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 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 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 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 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 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, 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; }
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 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 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 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 let mut buf = IoctlData {
1063 ..Default::default()
1064 };
1065 let in_size = in_size as usize;
1066 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 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 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 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 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 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 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, 0x0u8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ];
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, 0x0u8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ];
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 let mut read_buf_fail = [
1544 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7u8, 0x3u8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ];
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 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}