From 72419736bdad62a82b81e8c870f5305d92a6d77d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 29 Jun 2022 16:47:50 +0200 Subject: [PATCH] s3:vfs_fileid: always add the 'nolock' behavior via file_id.extid file_id.extid was filled with getpid() by 'fsname_norootdir_ext'. However instead of forcing the existing 'hostname' algorithm for the 'nolock' case, we'll now generate file_id.extid also based the hostname, vnn and for 'fsname_norootdir_ext' also the pid. This simplifies further changes and gives us the ability to generate stable results for file_id.{devid,inode} based on the main algorithm. This is important as we have a push_file_id_16() helper function used in places to generate a stable identifier of the file that is also client visible and might be stored on stable storage (acl_tdb, xattr_tdb). While the file_id.extid is only used internally in volatile databases. Review with: git show --patience Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme --- source3/modules/vfs_fileid.c | 55 +++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/source3/modules/vfs_fileid.c b/source3/modules/vfs_fileid.c index 7f235aaddb4..ff1432c8457 100644 --- a/source3/modules/vfs_fileid.c +++ b/source3/modules/vfs_fileid.c @@ -51,6 +51,7 @@ struct fileid_handle_data { unsigned num_mount_entries; struct fileid_mount_entry *mount_entries; struct { + uint64_t extid; size_t num_inodes; struct fileid_nolock_inode *inodes; } nolock; @@ -330,37 +331,38 @@ static int fileid_add_nolock_inode(struct fileid_handle_data *data, return 0; } -/* a device mapping using a fsname for files and hostname for dirs */ -static struct file_id fileid_mapping_fsname_nodirs( - struct fileid_handle_data *data, - const SMB_STRUCT_STAT *sbuf) +static uint64_t fileid_mapping_nolock_extid(uint64_t max_slots) { - if (S_ISDIR(sbuf->st_ex_mode)) { - return fileid_mapping_hostname(data, sbuf); + char buf[8+4+HOST_NAME_MAX+1] = { 0, }; + uint64_t slot = 0; + uint64_t id; + int rc; + + if (max_slots > 1) { + slot = getpid() % max_slots; } - return fileid_mapping_fsname(data, sbuf); -} + PUSH_LE_U64(buf, 0, slot); + PUSH_LE_U32(buf, 8, get_my_vnn()); -static struct file_id fileid_mapping_fsname_norootdir( - struct fileid_handle_data *data, - const SMB_STRUCT_STAT *sbuf) -{ - if (fileid_is_nolock_inode(data, sbuf)) { - return fileid_mapping_hostname(data, sbuf); + rc = gethostname(&buf[12], HOST_NAME_MAX+1); + if (rc != 0) { + DBG_ERR("gethostname failed\n"); + return UINT64_MAX; } - return fileid_mapping_fsname(data, sbuf); + id = fileid_uint64_hash((uint8_t *)buf, ARRAY_SIZE(buf)); + + return id; } -static struct file_id fileid_mapping_fsname_norootdir_ext( +/* a device mapping using a fsname for files and hostname for dirs */ +static struct file_id fileid_mapping_fsname_nodirs( struct fileid_handle_data *data, const SMB_STRUCT_STAT *sbuf) { - if (fileid_is_nolock_inode(data, sbuf)) { - struct file_id id = fileid_mapping_hostname(data, sbuf); - id.extid = getpid(); - return id; + if (S_ISDIR(sbuf->st_ex_mode)) { + return fileid_mapping_hostname(data, sbuf); } return fileid_mapping_fsname(data, sbuf); @@ -469,6 +471,7 @@ static int fileid_connect(struct vfs_handle_struct *handle, const char **mntdir_deny_list = NULL; const char **mntdir_allow_list = NULL; ino_t nolockinode; + uint64_t max_slots = 0; bool rootdir_nolock = false; int saved_errno; int ret = SMB_VFS_NEXT_CONNECT(handle, service, user); @@ -506,11 +509,12 @@ static int fileid_connect(struct vfs_handle_struct *handle, } else if (strcmp("hostname", algorithm) == 0) { data->mapping_fn = fileid_mapping_hostname; } else if (strcmp("fsname_norootdir", algorithm) == 0) { - data->mapping_fn = fileid_mapping_fsname_norootdir; + data->mapping_fn = fileid_mapping_fsname; rootdir_nolock = true; } else if (strcmp("fsname_norootdir_ext", algorithm) == 0) { - data->mapping_fn = fileid_mapping_fsname_norootdir_ext; + data->mapping_fn = fileid_mapping_fsname; rootdir_nolock = true; + max_slots = UINT64_MAX; } else if (strcmp("next_module", algorithm) == 0) { data->mapping_fn = fileid_mapping_next_module; } else { @@ -571,6 +575,10 @@ static int fileid_connect(struct vfs_handle_struct *handle, } } + max_slots = MAX(max_slots, 1); + + data->nolock.extid = fileid_mapping_nolock_extid(max_slots); + nolockinode = lp_parm_ulong(SNUM(handle->conn), "fileid", "nolockinode", 0); if (nolockinode != 0) { SMB_STRUCT_STAT tmpsbuf = { .st_ex_ino = nolockinode, }; @@ -636,6 +644,9 @@ static struct file_id fileid_file_id_create(struct vfs_handle_struct *handle, return id); id = data->mapping_fn(data, sbuf); + if (id.extid == 0 && fileid_is_nolock_inode(data, sbuf)) { + id.extid = data->nolock.extid; + } DBG_DEBUG("Returning dev [%jx] inode [%jx] extid [%jx]\n", (uintmax_t)id.devid, (uintmax_t)id.inode, (uintmax_t)id.extid); -- 2.47.3