macro_rules! handle_fuse_reply_entry {
($reply_executor:expr, $handler:expr, $resolver:expr, $req:expr, $parent:expr, $name:expr, $reply:expr,
$function:ident, ($($args:expr),*)) => {
macro_rules! if_lookup {
(lookup, $choice1:tt, $choice2:tt) => {
$choice1
};
($any:tt, $choice1:tt, $choice2:tt) => {
$choice2
};
}
let handler = $handler;
match handler.$function($($args),*) {
Ok(metadata) => {
let default_ttl = handler.get_default_ttl();
execute_reply_task!(
$reply_executor,
{
let (id, file_attr) = TId::extract_metadata(metadata);
let ino = $resolver.lookup($parent, $name, id, true);
let (fuse_attr, ttl, generation) = file_attr.to_fuse(ino);
$reply.entry(
&ttl.unwrap_or(default_ttl),
&fuse_attr,
generation.unwrap_or(get_random_generation()),
);
}
);
}
Err(e) => {
if_lookup!($function, {
if e.kind() == ErrorKind::FileNotFound {
info!("{}: parent_ino {:x?}, [{}], {:?}", stringify!($function), $parent, e, $req);
} else {
warn!("{}: parent_ino {:x?}, [{}], {:?}", stringify!($function), $parent, e, $req);
};
}, {
warn!("{}: parent_ino {:x?}, [{}], {:?}", stringify!($function), $parent, e, $req);
});
execute_reply_task!(
$reply_executor,
{
$reply.error(e.raw_error())
}
);
}
}
};
}
macro_rules! handle_fuse_reply_attr {
($reply_executor:expr, $handler:expr, $resolve:expr, $req:expr, $ino:expr, $reply:expr,
$function:ident, ($($args:expr),*)) => {
match $handler.$function($($args),*) {
Ok(file_attr) => {
let default_ttl = $handler.get_default_ttl();
execute_reply_task!(
$reply_executor,
{
let (fuse_attr, ttl, _) = file_attr.to_fuse($ino);
$reply.attr(&ttl.unwrap_or(default_ttl), &fuse_attr);
}
);
}
Err(e) => {
warn!("{}: ino {:x?}, [{}], {:?}", stringify!($function), $ino, e, $req);
execute_reply_task!(
$reply_executor,
{
$reply.error(e.raw_error())
}
);
}
}
};
}
macro_rules! handle_dir_read {
($self:expr, $req:expr, $ino:expr, $fh:expr, $offset:expr, $reply:expr,
$handler_method:ident, $get_iter_method:ident, $reply_type:ty) => {{
macro_rules! if_readdir {
(readdir, $choice1:tt, $choice2:tt) => {
$choice1
};
(readdirplus, $choice1:tt, $choice2:tt) => {
$choice2
};
}
let req_info = RequestInfo::from($req);
let handler = $self.get_handler();
let resolver = $self.get_resolver();
let dirmap_iter = $self.$get_iter_method();
#[cfg_attr(feature = "serial", allow(unused_variables))]
let reply_executor = reply_executor!($self);
execute_task!($self, {
if $offset < 0 {
error!("readdir called with a negative offset");
execute_reply_task!(reply_executor, {
$reply.error(ErrorKind::InvalidArgument.into());
});
return;
}
let mut dir_iter = match $offset {
0 => match handler.$handler_method(&req_info, resolver.resolve_id($ino), unsafe {
BorrowedFileHandle::from_raw($fh)
}) {
Ok(children) => {
let (child_list, attr_list): (Vec<_>, Vec<_>) = children
.into_iter()
.map(|item| {
let (child_id, child_attr) = if_readdir!(
$handler_method,
{ TId::extract_minimal_metadata(item.1) },
{ TId::extract_metadata(item.1) }
);
((item.0, child_id), child_attr)
})
.unzip();
resolver
.add_children(
$ino,
child_list,
if_readdir!($handler_method, false, true),
)
.into_iter()
.zip(attr_list.into_iter())
.map(|((file_name, file_ino), file_attr)| {
(file_name, file_ino, file_attr)
})
.collect()
}
Err(e) => {
warn!("readdir {:?}: {:?}", req_info, e);
execute_reply_task!(reply_executor, {
$reply.error(e.raw_error());
});
return;
}
},
_ => match { dirmap_iter.safe_borrow_mut().remove(&($ino, $offset)) } {
Some(dirmap_iter) => dirmap_iter,
None => {
execute_reply_task!(reply_executor, {
$reply.ok();
});
return;
}
},
};
let mut new_offset = $offset;
execute_reply_task!(reply_executor, {
if_readdir!(
$handler_method,
{
while let Some((name, ino, kind)) = dir_iter.pop_front() {
if $reply.add(ino, new_offset, kind, &name) {
dir_iter.push_front((name, ino, kind));
dirmap_iter
.safe_borrow_mut()
.insert(($ino, new_offset - 1), dir_iter);
break;
}
new_offset += 1;
}
$reply.ok();
},
{
let default_ttl = handler.get_default_ttl();
while let Some((name, ino, file_attr)) = dir_iter.pop_front() {
let (fuse_attr, ttl, generation) = file_attr.clone().to_fuse(ino);
if $reply.add(
ino,
new_offset,
&name,
&ttl.unwrap_or(default_ttl),
&fuse_attr,
generation.unwrap_or(get_random_generation()),
) {
dir_iter.push_front((name, ino, file_attr.clone()));
dirmap_iter
.safe_borrow_mut()
.insert((ino, new_offset - 1), dir_iter);
break;
}
new_offset += 1;
}
$reply.ok();
}
);
});
});
}};
}
pub(super) use handle_dir_read;
pub(super) use handle_fuse_reply_attr;
pub(super) use handle_fuse_reply_entry;