mirror of
https://github.com/systemd/systemd.git
synced 2025-01-18 10:04:04 +03:00
mountpoint-util: add new helper name_to_handle_at_try_fid()
Newer kernels support a new flag for name_to_handle_at(): AT_HANDLE_FID. This flag is supposed to return an identifier for an inode that we can use for checking inode identity. It's supposed to be a replacement for checking .st_ino which doesn't work anymore today because inode numbers are no longer unique on file systems (not on overlayfs, and not on btrfs for example). Hence, be a good citizen and add infrastructure to support AT_HANDLE_FID. Unfortunately that doesn't work for old kernels, hence add a fallback logic: if we can use the flag, use it. If we cannot use name_to_handle_at() without it, which might give us a good ID too. But of course tha tcan fail as well, which callers have to check.
This commit is contained in:
parent
6fba9a28b9
commit
81995fbb96
@ -92,3 +92,7 @@
|
||||
#define RAW_O_LARGEFILE 00100000
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef AT_HANDLE_FID
|
||||
#define AT_HANDLE_FID AT_REMOVEDIR
|
||||
#endif
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "fileio.h"
|
||||
#include "filesystems.h"
|
||||
#include "fs-util.h"
|
||||
#include "missing_fcntl.h"
|
||||
#include "missing_fs.h"
|
||||
#include "missing_mount.h"
|
||||
#include "missing_stat.h"
|
||||
@ -62,7 +63,8 @@ int name_to_handle_at_loop(
|
||||
|
||||
size_t n = ORIGINAL_MAX_HANDLE_SZ;
|
||||
|
||||
assert((flags & ~(AT_SYMLINK_FOLLOW|AT_EMPTY_PATH)) == 0);
|
||||
assert(fd >= 0 || fd == AT_FDCWD);
|
||||
assert((flags & ~(AT_SYMLINK_FOLLOW|AT_EMPTY_PATH|AT_HANDLE_FID)) == 0);
|
||||
|
||||
/* We need to invoke name_to_handle_at() in a loop, given that it might return EOVERFLOW when the specified
|
||||
* buffer is too small. Note that in contrast to what the docs might suggest, MAX_HANDLE_SZ is only good as a
|
||||
@ -119,6 +121,30 @@ int name_to_handle_at_loop(
|
||||
}
|
||||
}
|
||||
|
||||
int name_to_handle_at_try_fid(
|
||||
int fd,
|
||||
const char *path,
|
||||
struct file_handle **ret_handle,
|
||||
int *ret_mnt_id,
|
||||
int flags) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(fd >= 0 || fd == AT_FDCWD);
|
||||
|
||||
/* First issues name_to_handle_at() with AT_HANDLE_FID. If this fails and this is not a fatal error
|
||||
* we'll try without the flag, in order to support older kernels that didn't have AT_HANDLE_FID
|
||||
* (i.e. older than Linux 6.5). */
|
||||
|
||||
r = name_to_handle_at_loop(fd, path, ret_handle, ret_mnt_id, flags | AT_HANDLE_FID);
|
||||
if (r >= 0)
|
||||
return r;
|
||||
if (is_name_to_handle_at_fatal_error(r))
|
||||
return r;
|
||||
|
||||
return name_to_handle_at_loop(fd, path, ret_handle, ret_mnt_id, flags & ~AT_HANDLE_FID);
|
||||
}
|
||||
|
||||
static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *ret_mnt_id) {
|
||||
char path[STRLEN("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)];
|
||||
_cleanup_free_ char *fdinfo = NULL;
|
||||
|
@ -39,6 +39,7 @@
|
||||
bool is_name_to_handle_at_fatal_error(int err);
|
||||
|
||||
int name_to_handle_at_loop(int fd, const char *path, struct file_handle **ret_handle, int *ret_mnt_id, int flags);
|
||||
int name_to_handle_at_try_fid(int fd, const char *path, struct file_handle **ret_handle, int *ret_mnt_id, int flags);
|
||||
|
||||
bool file_handle_equal(const struct file_handle *a, const struct file_handle *b);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user