fix #4975: client: ignore E2BIG error flag

Some filesystems (f.e. zfs) support xattrs bigger than 64kB, sadly we
can't get them because the kernel vfs limits us. The syscalls listxattr
and getxattr will return a E2BIG error in this case.
Added a flag --ignore-e2big-xattr to the client, this will ignore the
metadata (but still backup the file) if this error occurs.

Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
This commit is contained in:
Gabriel Goller 2024-02-14 10:52:01 +01:00 committed by Dietmar Maurer
parent 55d50f1344
commit a602a885af
4 changed files with 35 additions and 1 deletions

View File

@ -41,6 +41,8 @@ pub struct PxarCreateOptions {
pub entries_max: usize,
/// Skip lost+found directory
pub skip_lost_and_found: bool,
/// Skip xattrs of files that return E2BIG error
pub skip_e2big_xattr: bool,
}
fn detect_fs_type(fd: RawFd) -> Result<i64, Error> {
@ -128,6 +130,7 @@ struct Archiver {
device_set: Option<HashSet<u64>>,
hardlinks: HashMap<HardLinkInfo, (PathBuf, LinkOffset)>,
file_copy_buffer: Vec<u8>,
skip_e2big_xattr: bool,
}
type Encoder<'a, T> = pxar::encoder::aio::Encoder<'a, T>;
@ -158,6 +161,7 @@ where
feature_flags & fs_feature_flags,
fs_magic,
&mut fs_feature_flags,
options.skip_e2big_xattr
)
.context("failed to get metadata for source directory")?;
@ -192,6 +196,7 @@ where
device_set,
hardlinks: HashMap::new(),
file_copy_buffer: vec::undefined(4 * 1024 * 1024),
skip_e2big_xattr: options.skip_e2big_xattr,
};
archiver
@ -540,6 +545,7 @@ impl Archiver {
self.flags(),
self.fs_magic,
&mut self.fs_feature_flags,
self.skip_e2big_xattr
)?;
let match_path = PathBuf::from("/").join(self.path.clone());
@ -765,6 +771,7 @@ fn get_metadata(
flags: Flags,
fs_magic: i64,
fs_feature_flags: &mut Flags,
skip_e2big_xattr: bool,
) -> Result<Metadata, Error> {
// required for some of these
let proc_path = Path::new("/proc/self/fd/").join(fd.to_string());
@ -780,7 +787,7 @@ fn get_metadata(
..Default::default()
};
get_xattr_fcaps_acl(&mut meta, fd, &proc_path, flags, fs_feature_flags)?;
get_xattr_fcaps_acl(&mut meta, fd, &proc_path, flags, fs_feature_flags, skip_e2big_xattr)?;
get_chattr(&mut meta, fd)?;
get_fat_attr(&mut meta, fd, fs_magic)?;
get_quota_project_id(&mut meta, fd, flags, fs_magic)?;
@ -818,6 +825,7 @@ fn get_xattr_fcaps_acl(
proc_path: &Path,
flags: Flags,
fs_feature_flags: &mut Flags,
skip_e2big_xattr: bool,
) -> Result<(), Error> {
if !flags.contains(Flags::WITH_XATTRS) {
return Ok(());
@ -829,6 +837,14 @@ fn get_xattr_fcaps_acl(
fs_feature_flags.remove(Flags::WITH_XATTRS);
return Ok(());
}
Err(Errno::E2BIG) => {
match skip_e2big_xattr {
true => return Ok(()),
false => {
bail!("{} (try --skip-e2big-xattr)", Errno::E2BIG.to_string());
}
};
}
Err(Errno::EBADF) => return Ok(()), // symlinks
Err(err) => return Err(err).context("failed to read xattrs"),
};
@ -855,6 +871,14 @@ fn get_xattr_fcaps_acl(
Err(Errno::ENODATA) => (), // it got removed while we were iterating...
Err(Errno::EOPNOTSUPP) => (), // shouldn't be possible so just ignore this
Err(Errno::EBADF) => (), // symlinks, shouldn't be able to reach this either
Err(Errno::E2BIG) => {
match skip_e2big_xattr {
true => return Ok(()),
false => {
bail!("{} (try --skip-e2big-xattr)", Errno::E2BIG.to_string());
}
};
}
Err(err) => {
return Err(err).context(format!("error reading extended attribute {attr:?}"))
}

View File

@ -665,6 +665,12 @@ fn spawn_catalog_upload(
optional: true,
default: false,
},
"skip-e2big-xattr": {
type: Boolean,
description: "Ignore the E2BIG error when retrieving xattrs. This includes the file, but discards the metadata.",
optional: true,
default: false,
},
}
}
)]
@ -674,6 +680,7 @@ async fn create_backup(
all_file_systems: bool,
skip_lost_and_found: bool,
dry_run: bool,
skip_e2big_xattr: bool,
_info: &ApiMethod,
_rpcenv: &mut dyn RpcEnvironment,
) -> Result<Value, Error> {
@ -993,6 +1000,7 @@ async fn create_backup(
patterns: pattern_list.clone(),
entries_max: entries_max as usize,
skip_lost_and_found,
skip_e2big_xattr
};
let upload_options = UploadOptions {

View File

@ -352,6 +352,7 @@ fn extract(
device_set: None,
patterns,
skip_lost_and_found: false,
skip_e2big_xattr: false,
};
let pxar_writer = TokioWriter::new(writer);

View File

@ -335,6 +335,7 @@ async fn create_archive(
device_set,
patterns,
skip_lost_and_found: false,
skip_e2big_xattr: false,
};
let source = PathBuf::from(source);