- diff --git a/cygwin/devel/msnfs41client.bash b/cygwin/devel/msnfs41client.bash
- index 4a391dd..8c7bfa4 100755
- --- a/cygwin/devel/msnfs41client.bash
- +++ b/cygwin/devel/msnfs41client.bash
- @@ -467,7 +467,7 @@ function nfsclient_rundeamon
- "${nfsd_args[@]}"
- )
- "${nfsd_args[@]}"
- - elif false ; then
- + elif true ; then
- export _NT_ALT_SYMBOL_PATH="$(cygpath -w "$PWD");srv*https://msdl.microsoft.com/download/symbols"
- #
- # Useful cdb cmds:
- @@ -601,7 +601,7 @@ function nfsclient_system_rundeamon
- )
- "${nfsd_args[@]}"
- - elif false ; then
- + elif true ; then
- export _NT_ALT_SYMBOL_PATH="$(cygpath -w "$PWD");srv*https://msdl.microsoft.com/download/symbols"
- # - heap tests (eats lots of memory):
- # '-c' '!gflag +full;g' for heap tests
- diff --git a/daemon/acl.c b/daemon/acl.c
- index 370f2d3..c655b3f 100644
- --- a/daemon/acl.c
- +++ b/daemon/acl.c
- @@ -326,62 +326,49 @@ static int handle_getacl(void *daemon_context, nfs41_upcall *upcall)
- PSID osid = NULL, gsid = NULL;
- DWORD sid_len;
- char owner[NFS4_FATTR4_OWNER_LIMIT+1], group[NFS4_FATTR4_OWNER_LIMIT+1];
- + bitmap4 owner_group_acl_bitmap = {
- + .count = 2,
- + .arr[0] = 0,
- + .arr[1] = FATTR4_WORD1_OWNER|FATTR4_WORD1_OWNER_GROUP
- + };
- nfsacl41 acl = { 0 };
- DPRINTF(ACLLVL1, ("--> handle_getacl(state->path.path='%s')\n",
- state->path.path));
- if (args->query & DACL_SECURITY_INFORMATION) {
- -use_nfs41_getattr:
- - bitmap4 attr_request = { 0 };
- - (void)memset(&info, 0, sizeof(nfs41_file_info));
- - info.owner = owner;
- - info.owner_group = group;
- -
- - attr_request.count = 2;
- - attr_request.arr[0] = FATTR4_WORD0_ACL;
- - attr_request.arr[1] = FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP;
- - info.acl = &acl;
- - status = nfs41_getattr(state->session, &state->file, &attr_request, &info);
- - if (status) {
- - eprintf("handle_getacl: nfs41_getattr() failed with %d\n",
- - status);
- - goto out;
- - }
- + owner_group_acl_bitmap.arr[0] |= FATTR4_WORD0_ACL;
- }
- - else {
- - (void)memset(&info, 0, sizeof(nfs41_file_info));
- - info.owner = owner;
- - info.owner_group = group;
- - status = nfs41_cached_getattr(state->session, &state->file, &info);
- - if (status) {
- - eprintf("handle_getacl: nfs41_cached_getattr() failed with %d\n",
- - status);
- - goto out;
- - }
- + (void)memset(&info, 0, sizeof(nfs41_file_info));
- + info.owner = owner;
- + info.owner_group = group;
- + info.acl = &acl;
- - EASSERT(info.attrmask.count > 1);
- -
- - /*
- - * In rare cases owner/owner_group are not in the cache
- - * (usually for new files). In this case do a full
- - * roundtrip to the NFS server to get the data...
- - */
- - if ((bitmap_isset(&info.attrmask, 1,
- - FATTR4_WORD1_OWNER) == false) ||
- - (bitmap_isset(&info.attrmask, 1,
- - FATTR4_WORD1_OWNER_GROUP) == false)) {
- - DPRINTF(ACLLVL2, ("handle_getattr: owner/owner_group not in cache, doing full lookup...\n"));
- - goto use_nfs41_getattr;
- - }
- + /*
- + * |nfs41_cached_getattr()| will first try to get all information from
- + * the cache. But if bits are missing (e.g. |FATTR4_WORD0_ACL|, because
- + * either not cached in the name cache, or name cache entry for ACLs
- + * expired...), then this will do a server roundtrip to get the missing
- + * data
- + */
- + status = nfs41_cached_getattr(state->session,
- + &state->file, &owner_group_acl_bitmap, &info);
- + if (status) {
- + eprintf("handle_getacl: nfs41_cached_getattr() failed with %d\n",
- + status);
- + goto out;
- }
- EASSERT(info.attrmask.count > 1);
- - EASSERT(bitmap_isset(&info.attrmask, 1, FATTR4_WORD1_OWNER) &&
- - bitmap_isset(&info.attrmask, 1, FATTR4_WORD1_OWNER_GROUP));
- if (args->query & DACL_SECURITY_INFORMATION) {
- - EASSERT(bitmap_isset(&info.attrmask, 0, FATTR4_WORD0_ACL));
- + EASSERT(bitmap_isset(&info.attrmask, 0, FATTR4_WORD0_ACL) == true);
- + }
- + if (args->query & OWNER_SECURITY_INFORMATION) {
- + EASSERT(bitmap_isset(&info.attrmask, 1, FATTR4_WORD1_OWNER) == true);
- + }
- + if (args->query & GROUP_SECURITY_INFORMATION) {
- + EASSERT(bitmap_isset(&info.attrmask, 1, FATTR4_WORD1_OWNER_GROUP) == true);
- }
- status = InitializeSecurityDescriptor(&sec_desc,
- @@ -433,6 +420,7 @@ use_nfs41_getattr:
- goto out;
- }
- }
- +
- if (args->query & DACL_SECURITY_INFORMATION) {
- DPRINTF(ACLLVL2, ("handle_getacl: DACL_SECURITY_INFORMATION\n"));
- status = convert_nfs4acl_2_dacl(nfs41dg,
- diff --git a/daemon/getattr.c b/daemon/getattr.c
- index 7c8b2d1..fb7a738 100644
- --- a/daemon/getattr.c
- +++ b/daemon/getattr.c
- @@ -37,18 +37,39 @@
- int nfs41_cached_getattr(
- IN nfs41_session *session,
- IN nfs41_path_fh *file,
- + IN OPTIONAL bitmap4 *extra_attr_request,
- OUT nfs41_file_info *info)
- {
- int status;
- + bool bits_missing = false;
- /* first look for cached attributes */
- status = nfs41_attr_cache_lookup(session_name_cache(session),
- file->fh.fileid, info);
- -
- - if (status) {
- +
- + if ((status == 0) && extra_attr_request) {
- + uint32_t i;
- +
- + /* Check if bits are missing... */
- + for (i=0 ; i < extra_attr_request->count ; i++) {
- + if ((extra_attr_request->arr[i] != 0) &&
- + ((((i < info->attrmask.count)?(info->attrmask.arr[i]):0) &
- + extra_attr_request->arr[i]) == 0)) {
- + bits_missing = true;
- + DPRINTF(1, ("nfs41_cached_getattr: bits missing %d\n", i));
- + break;
- + }
- + }
- + }
- +
- + if (status || bits_missing) {
- /* fetch attributes from the server */
- bitmap4 attr_request;
- - nfs41_superblock_getattr_mask(file->fh.superblock, &attr_request);
- + nfs41_superblock_getattr_mask(file->fh.superblock, &attr_request);
- +
- + if (extra_attr_request) {
- + bitmap_or(&attr_request, extra_attr_request);
- + }
- status = nfs41_getattr(session, file, &attr_request, info);
- if (status) {
- @@ -88,7 +109,7 @@ static int handle_getattr(void *daemon_context, nfs41_upcall *upcall)
- nfs41_open_state *state = upcall->state_ref;
- nfs41_file_info info = { 0 };
- - status = nfs41_cached_getattr(state->session, &state->file, &info);
- + status = nfs41_cached_getattr(state->session, &state->file, NULL, &info);
- if (status) {
- eprintf("handle_getattr(state->path.path='%s'): "
- "nfs41_cached_getattr() failed with %d\n",
- @@ -98,7 +119,7 @@ static int handle_getattr(void *daemon_context, nfs41_upcall *upcall)
- }
- if (info.type == NF4LNK) {
- - nfs41_file_info target_info;
- + nfs41_file_info target_info = { 0 };
- int target_status = nfs41_symlink_follow(upcall->root_ref,
- state->session, &state->file, &target_info);
- if (target_status == NO_ERROR) {
- diff --git a/daemon/name_cache.c b/daemon/name_cache.c
- index 950c188..2c9d90d 100644
- --- a/daemon/name_cache.c
- +++ b/daemon/name_cache.c
- @@ -31,6 +31,7 @@
- #include "util.h"
- #include "tree.h"
- #include "daemon_debug.h"
- +#include "nfs41_driver.h" /* for |NFS41_ACL_CACHE_EXPIRATION| */
- /* dprintf levels for name cache logging */
- @@ -41,6 +42,7 @@ enum {
- #define NAME_CACHE_EXPIRATION 30 /* TODO: get from configuration */
- +#define NAME_CACHE_ACL_EXPIRATION NFS41_ACL_CACHE_EXPIRATION
- /* allow up to 32M of memory for name and attribute cache entries */
- #define NAME_CACHE_MAX_SIZE (32*1024*1024L)
- @@ -87,11 +89,12 @@ static __inline bool_t is_delegation(
- #define NC_ATTR_NUMLINKS (1 << 8)
- #define NC_ATTR_OWNER (1 << 9)
- #define NC_ATTR_OWNER_GROUP (1 << 10)
- -#define NC_ATTR_TIME_ACCESS (1 << 11)
- -#define NC_ATTR_TIME_CREATE (1 << 12)
- -#define NC_ATTR_TIME_MODIFY (1 << 13)
- -#define NC_ATTR_SYSTEM (1 << 14)
- -#define NC_ATTR_CLONE_BLKSIZE (1 << 15)
- +#define NC_ATTR_ACL (1 << 11)
- +#define NC_ATTR_TIME_ACCESS (1 << 12)
- +#define NC_ATTR_TIME_CREATE (1 << 13)
- +#define NC_ATTR_TIME_MODIFY (1 << 14)
- +#define NC_ATTR_SYSTEM (1 << 15)
- +#define NC_ATTR_CLONE_BLKSIZE (1 << 16)
- /* attribute cache */
- struct attr_cache_entry {
- @@ -123,6 +126,8 @@ struct attr_cache_entry {
- unsigned delegated : 1;
- char owner[NFS4_FATTR4_OWNER_LIMIT+1];
- char owner_group[NFS4_FATTR4_OWNER_LIMIT+1];
- + util_reltimestamp acl_expiration;
- + nfsacl41 acl;
- };
- #define ATTR_ENTRY_SIZE sizeof(struct attr_cache_entry)
- @@ -169,6 +174,7 @@ static int attr_cache_entry_create(
- entry->fsid_minor = 0ULL;
- entry->invalidated = FALSE;
- entry->delegated = FALSE;
- + (void)memset(&entry->acl, 0, sizeof(nfsacl41));
- *entry_out = entry;
- out:
- return status;
- @@ -180,6 +186,12 @@ static __inline void attr_cache_entry_free(
- {
- DPRINTF(NCLVL1, ("attr_cache_entry_free(%llu)\n", entry->fileid));
- RB_REMOVE(attr_tree, &cache->head, entry);
- +
- + if (entry->acl.aces) {
- + free(entry->acl.aces);
- + entry->acl.aces = NULL;
- + }
- +
- /* add it back to free_entries */
- list_add_tail(&cache->free_entries, &entry->free_entry);
- }
- @@ -344,6 +356,22 @@ static void attr_cache_update(
- entry->nc_attrs |= NC_ATTR_ARCHIVE;
- entry->archive = info->archive;
- }
- + if (info->attrmask.arr[0] & FATTR4_WORD0_ACL) {
- + if (entry->acl.aces) {
- + free(entry->acl.aces);
- + entry->acl.aces = NULL;
- + }
- +
- + entry->nc_attrs &= ~NC_ATTR_ACL;
- +
- + if (info->acl) {
- + entry->acl_expiration = UTIL_GETRELTIME() +
- + NAME_CACHE_ACL_EXPIRATION;
- + entry->nc_attrs |= NC_ATTR_ACL;
- + (void)dup_nfsacl41aces(&entry->acl, info->acl);
- + EASSERT(entry->acl.aces != NULL);
- + }
- + }
- }
- if (info->attrmask.count > 1) {
- if (info->attrmask.arr[1] & FATTR4_WORD1_MODE) {
- @@ -463,6 +491,22 @@ static void copy_attrs(
- /* this should only happen for newly created files/dirs */
- dst->owner_group = NULL;
- }
- + if (src->nc_attrs & NC_ATTR_ACL) {
- + /*
- + * 1. Only copy attribute if |dst| provides a pointer to an ACL struct
- + * This implicitly solves the issue who will free |dst->acl.aces|,
- + * because only who provides a |dst->acl| will get ACL/ACE data,
- + * but then also has to free the |dst->acl.aces| data.
- + * 2. Only copy data and |FATTR4_WORD0_ACL| if |acl_expiration| did
- + * not indicate expiration. This has a subtle interaction with
- + * |handle_getacl()|, where |nfs41_cached_getattr()| will fall-back
- + * to do a server lookup if the |FATTR4_WORD0_ACL| bit is missing.
- + */
- + if (dst->acl && (UTIL_GETRELTIME() <= src->acl_expiration)) {
- + dst->attrmask.arr[0] |= FATTR4_WORD0_ACL;
- + (void)dup_nfsacl41aces(dst->acl, &src->acl);
- + }
- + }
- if (src->nc_attrs & NC_ATTR_FSID) {
- dst->attrmask.arr[0] |= FATTR4_WORD0_FSID;
- dst->fsid.major = src->fsid_major;
- diff --git a/daemon/nfs41_ops.c b/daemon/nfs41_ops.c
- index 862ce0e..b5cda90 100644
- --- a/daemon/nfs41_ops.c
- +++ b/daemon/nfs41_ops.c
- @@ -1478,28 +1478,30 @@ int nfs41_setattr(
- nfs41_superblock_getattr_mask(file->fh.superblock, &attr_request);
- - if (info->attrmask.count >= 2) {
- - /*
- - * If we set owner and/or owner_group make sure we ask
- - * the server to send the values back for two reasons:
- - * 1, Handle cases like "all_squash" (e.g. nfsd turns
- - * owner/owner_group always into "nobody"/"nogroup")
- - * 2. Make sure we update the name cache with the new
- - * owner/owner_group
- - *
- - * Note that this can be a bit tricky as we might pass
- - * a "name@domain" string to the server, but get a numeric
- - * uid/gid as strings back, which means the name cache
- - * might have both representations.
- - */
- - if (info->attrmask.arr[1] & FATTR4_WORD1_OWNER) {
- - attr_request.count = 2;
- - attr_request.arr[1] |= FATTR4_WORD1_OWNER;
- - }
- - if (info->attrmask.arr[1] & FATTR4_WORD1_OWNER_GROUP) {
- - attr_request.count = 2;
- - attr_request.arr[1] |= FATTR4_WORD1_OWNER_GROUP;
- - }
- + /*
- + * If we set owner, owner_group and/or ACLs make sure we ask
- + * the server to send the values back for two reasons:
- + * 1, Handle cases like "all_squash" (e.g. nfsd turns
- + * owner/owner_group always into "nobody"/"nogroup")
- + * 2. Make sure we update the name cache with the new
- + * owner/owner_group/ACLs
- + *
- + * Note that this can be a bit tricky as we might pass
- + * a "name@domain" string to the server, but get a numeric
- + * uid/gid as strings back, which means the name cache
- + * might have both representations.
- + */
- + if (bitmap_isset(&info->attrmask, 0, FATTR4_WORD0_ACL)) {
- + attr_request.count = __max(attr_request.count, 1);
- + attr_request.arr[0] |= FATTR4_WORD0_ACL;
- + }
- + if (bitmap_isset(&info->attrmask, 1, FATTR4_WORD1_OWNER)) {
- + attr_request.count = __max(attr_request.count, 2);
- + attr_request.arr[1] |= FATTR4_WORD1_OWNER;
- + }
- + if (bitmap_isset(&info->attrmask, 1, FATTR4_WORD1_OWNER_GROUP)) {
- + attr_request.count = __max(attr_request.count, 2);
- + attr_request.arr[1] |= FATTR4_WORD1_OWNER_GROUP;
- }
- compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res);
- diff --git a/daemon/nfs41_ops.h b/daemon/nfs41_ops.h
- index f57f8dc..91cb766 100644
- --- a/daemon/nfs41_ops.h
- +++ b/daemon/nfs41_ops.h
- @@ -1331,6 +1331,7 @@ int nfs41_superblock_getattr(
- int nfs41_cached_getattr(
- IN nfs41_session *session,
- IN nfs41_path_fh *file,
- + IN OPTIONAL bitmap4 *extra_attr_request,
- OUT nfs41_file_info *info);
- int nfs41_remove(
- diff --git a/daemon/nfs41_xdr.c b/daemon/nfs41_xdr.c
- index 4ccbeaa..d9e3629 100644
- --- a/daemon/nfs41_xdr.c
- +++ b/daemon/nfs41_xdr.c
- @@ -1779,6 +1779,9 @@ static bool_t decode_file_attrs(
- }
- if (attrs->attrmask.arr[0] & FATTR4_WORD0_ACL) {
- nfsacl41 *acl = info->acl;
- +
- + EASSERT(acl != NULL);
- +
- if (!xdr_array(xdr, (char**)&acl->aces, &acl->count,
- NFS41_ACL_MAX_ACE_ENTRIES, sizeof(nfsace4),
- (xdrproc_t)xdr_nfsace4))
- diff --git a/daemon/open.c b/daemon/open.c
- index aeaae11..2ba788a 100644
- --- a/daemon/open.c
- +++ b/daemon/open.c
- @@ -867,7 +867,7 @@ static int handle_open(void *daemon_context, nfs41_upcall *upcall)
- if (args->create_opts & FILE_OPEN_REPARSE_POINT) {
- /* continue and open the symlink itself, but we need to
- * know if the target is a regular file or directory */
- - nfs41_file_info target_info;
- + nfs41_file_info target_info = { 0 };
- int target_status = nfs41_symlink_follow(upcall->root_ref,
- state->session, &state->file, &target_info);
- if (target_status == NO_ERROR) {
- diff --git a/daemon/readdir.c b/daemon/readdir.c
- index f3564bf..a754197 100644
- --- a/daemon/readdir.c
- +++ b/daemon/readdir.c
- @@ -515,7 +515,7 @@ static int lookup_symlink(
- {
- nfs41_abs_path path;
- nfs41_path_fh file;
- - nfs41_file_info info;
- + nfs41_file_info info = { 0 };
- int status;
- status = format_abs_path(parent->path, name, &path);
- @@ -686,7 +686,7 @@ static int readdir_add_dots(
- ZeroMemory(&entry->attr_info, sizeof(nfs41_file_info));
- status = nfs41_cached_getattr(state->session,
- - &state->file, &entry->attr_info);
- + &state->file, NULL, &entry->attr_info);
- if (status) {
- DPRINTF(0, ("readdir_add_dots: failed to add '.' entry.\n"));
- goto out;
- @@ -719,7 +719,7 @@ static int readdir_add_dots(
- ZeroMemory(&entry->attr_info, sizeof(nfs41_file_info));
- status = nfs41_cached_getattr(state->session,
- - &state->parent, &entry->attr_info);
- + &state->parent, NULL, &entry->attr_info);
- if (status) {
- status = ERROR_FILE_NOT_FOUND;
- DPRINTF(0, ("readdir_add_dots: failed to add '..' entry.\n"));
- diff --git a/daemon/setattr.c b/daemon/setattr.c
- index 1e2bfdd..a994548 100644
- --- a/daemon/setattr.c
- +++ b/daemon/setattr.c
- @@ -71,7 +71,7 @@ static int handle_nfs41_setattr_basicinfo(void *daemon_context, setattr_upcall_a
- (void)memset(&old_info, 0, sizeof(old_info));
- getattr_status = nfs41_cached_getattr(state->session,
- - &state->file, &old_info);
- + &state->file, NULL, &old_info);
- if (getattr_status) {
- DPRINTF(0, ("handle_nfs41_setattr_basicinfo(args->path='%s'): "
- "nfs41_cached_getattr() failed with error %d.\n",
- diff --git a/daemon/util.c b/daemon/util.c
- index 3a56b7c..535bad7 100644
- --- a/daemon/util.c
- +++ b/daemon/util.c
- @@ -638,3 +638,21 @@ bool getwinntversionnnumbers(
- return false;
- #endif /* _WIN64 */
- }
- +
- +bool dup_nfsacl41aces(
- + nfsacl41 *restrict out_acl,
- + const nfsacl41 *restrict in_acl)
- +{
- + size_t acemem_size = in_acl->count * sizeof(nfsace4);
- +
- + out_acl->aces = wintirpc_mem_alloc(acemem_size);
- + if (out_acl->aces == NULL) {
- + return false;
- + }
- +
- + out_acl->count = in_acl->count;
- + out_acl->flag = in_acl->flag;
- + (void)memcpy(out_acl->aces, in_acl->aces, acemem_size);
- +
- + return true;
- +}
- diff --git a/daemon/util.h b/daemon/util.h
- index 6938372..9c558af 100644
- --- a/daemon/util.h
- +++ b/daemon/util.h
- @@ -376,4 +376,6 @@ bool_t waitcriticalsection(LPCRITICAL_SECTION cs);
- bool getwinntversionnnumbers(DWORD *MajorVersionPtr, DWORD *MinorVersionPtr, DWORD *BuildNumberPtr);
- +bool dup_nfsacl41aces(nfsacl41 *restrict out_acl, const nfsacl41 *restrict in_acl);
- +
- #endif /* !__NFS41_DAEMON_UTIL_H__ */
- diff --git a/include/nfs41_driver.h b/include/nfs41_driver.h
- index e11ebf5..06e8cfa 100644
- --- a/include/nfs41_driver.h
- +++ b/include/nfs41_driver.h
- @@ -127,6 +127,8 @@ typedef enum _nfs41_start_driver_state {
- #define NFS_VERSION_AUTONEGOTIATION (0xFFFF)
- +/* Cache NFSv4.1 ACLs for max. 20 seconds */
- +#define NFS41_ACL_CACHE_EXPIRATION (20)
- /*
- * LargeInteger.QuadPart value to indicate a time value was not
- * available
- diff --git a/sys/nfs41sys_acl.c b/sys/nfs41sys_acl.c
- index c468433..f7437a4 100644
- --- a/sys/nfs41sys_acl.c
- +++ b/sys/nfs41sys_acl.c
- @@ -235,7 +235,8 @@ NTSTATUS nfs41_QuerySecurityInformation(
- (long long)current_time.QuadPart,
- (long long)nfs41_fobx->time.QuadPart);
- #endif
- - if (current_time.QuadPart - nfs41_fobx->time.QuadPart <= 20*1000) {
- + if ((current_time.QuadPart - nfs41_fobx->time.QuadPart) <=
- + (NFS41_ACL_CACHE_EXPIRATION*1000)) {
- PSECURITY_DESCRIPTOR sec_desc = (PSECURITY_DESCRIPTOR)
- RxContext->CurrentIrp->UserBuffer;
- RtlCopyMemory(sec_desc, nfs41_fobx->acl, nfs41_fobx->acl_len);
ACL support in name cache
Posted by Anonymous on Wed 25th Jun 2025 18:30
raw | new post
modification of post by Anonymous (view diff)
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.