pastebin - collaborative debugging tool
nrubsig.kpaste.net RSS


ACL support in name cache
Posted by Anonymous on Mon 23rd Jun 2025 20:24
raw | new post
view followups (newest first): ACL support in name cache by Anonymous

  1. diff --git a/cygwin/devel/msnfs41client.bash b/cygwin/devel/msnfs41client.bash
  2. index 4a391dd..8c7bfa4 100755
  3. --- a/cygwin/devel/msnfs41client.bash
  4. +++ b/cygwin/devel/msnfs41client.bash
  5. @@ -467,7 +467,7 @@ function nfsclient_rundeamon
  6.                         "${nfsd_args[@]}"
  7.                 )
  8.                 "${nfsd_args[@]}"
  9. -       elif false ; then
  10. +       elif true ; then
  11.                 export _NT_ALT_SYMBOL_PATH="$(cygpath -w "$PWD");srv*https://msdl.microsoft.com/download/symbols"
  12.                 #
  13.                 # Useful cdb cmds:
  14. @@ -601,7 +601,7 @@ function nfsclient_system_rundeamon
  15.                 )
  16.  
  17.                 "${nfsd_args[@]}"
  18. -       elif false ; then
  19. +       elif true ; then
  20.                 export _NT_ALT_SYMBOL_PATH="$(cygpath -w "$PWD");srv*https://msdl.microsoft.com/download/symbols"
  21.                 # - heap tests (eats lots of memory):
  22.                 # '-c' '!gflag +full;g' for heap tests
  23. diff --git a/daemon/acl.c b/daemon/acl.c
  24. index 370f2d3..4e3c0f9 100644
  25. --- a/daemon/acl.c
  26. +++ b/daemon/acl.c
  27. @@ -331,8 +331,53 @@ static int handle_getacl(void *daemon_context, nfs41_upcall *upcall)
  28.      DPRINTF(ACLLVL1, ("--> handle_getacl(state->path.path='%s')\n",
  29.          state->path.path));
  30.  
  31. -    if (args->query & DACL_SECURITY_INFORMATION) {
  32. -use_nfs41_getattr:
  33. +    (void)memset(&info, 0, sizeof(nfs41_file_info));
  34. +    info.owner = owner;
  35. +    info.owner_group = group;
  36. +    info.acl = &acl;
  37. +
  38. +    status = nfs41_cached_getattr(state->session, &state->file, &info);
  39. +    if (status) {
  40. +        eprintf("handle_getacl: nfs41_cached_getattr() failed with %d\n",
  41. +            status);
  42. +        goto out;
  43. +    }
  44. +
  45. +    EASSERT(info.attrmask.count > 1);
  46. +    bool do_full_lookup = false;
  47. +
  48. +    /*
  49. +     * In rare cases owner/owner_group are not in the cache
  50. +     * (usually for new files). In this case do a full
  51. +     * roundtrip to the NFS server to get the data...
  52. +     */
  53. +    if ((bitmap_isset(&info.attrmask, 1,
  54. +            FATTR4_WORD1_OWNER) == false) ||
  55. +        (bitmap_isset(&info.attrmask, 1,
  56. +            FATTR4_WORD1_OWNER_GROUP) == false)) {
  57. +        DPRINTF(ACLLVL2,
  58. +            ("handle_getattr: "
  59. +            "owner/owner_group not in cache, doing full lookup...\n"));
  60. +        do_full_lookup = true;
  61. +    }
  62. +
  63. +    if ((args->query & DACL_SECURITY_INFORMATION) &&
  64. +        (bitmap_isset(&info.attrmask, 0, FATTR4_WORD0_ACL) == false)) {
  65. +        DPRINTF(0,
  66. +            ("handle_getattr: "
  67. +            "ACL information not in cache, doing full lookup...\n"));
  68. +        do_full_lookup = true;
  69. +    }
  70. +
  71. +#if 1
  72. +    /* debug */
  73. +    if ((args->query & DACL_SECURITY_INFORMATION) &&
  74. +        (do_full_lookup == false)) {
  75. +        DPRINTF(0, ("handle_getacl: cached ACL used\n"));
  76. +    }
  77. +#endif
  78. +
  79. +    if (do_full_lookup) {
  80.          bitmap4 attr_request = { 0 };
  81.          (void)memset(&info, 0, sizeof(nfs41_file_info));
  82.          info.owner = owner;
  83. @@ -349,40 +394,11 @@ use_nfs41_getattr:
  84.              goto out;
  85.          }
  86.      }
  87. -    else {
  88. -        (void)memset(&info, 0, sizeof(nfs41_file_info));
  89. -        info.owner = owner;
  90. -        info.owner_group = group;
  91.  
  92. -        status = nfs41_cached_getattr(state->session, &state->file, &info);
  93. -        if (status) {
  94. -            eprintf("handle_getacl: nfs41_cached_getattr() failed with %d\n",
  95. -                status);
  96. -            goto out;
  97. -        }
  98. -
  99. -        EASSERT(info.attrmask.count > 1);
  100. -
  101. -        /*
  102. -         * In rare cases owner/owner_group are not in the cache
  103. -         * (usually for new files). In this case do a full
  104. -         * roundtrip to the NFS server to get the data...
  105. -         */
  106. -        if ((bitmap_isset(&info.attrmask, 1,
  107. -                FATTR4_WORD1_OWNER) == false) ||
  108. -            (bitmap_isset(&info.attrmask, 1,
  109. -                FATTR4_WORD1_OWNER_GROUP) == false)) {
  110. -            DPRINTF(ACLLVL2, ("handle_getattr: owner/owner_group not in cache, doing full lookup...\n"));
  111. -            goto use_nfs41_getattr;
  112. -        }
  113. -    }
  114.  
  115.      EASSERT(info.attrmask.count > 1);
  116.      EASSERT(bitmap_isset(&info.attrmask, 1, FATTR4_WORD1_OWNER) &&
  117.          bitmap_isset(&info.attrmask, 1, FATTR4_WORD1_OWNER_GROUP));
  118. -    if (args->query & DACL_SECURITY_INFORMATION) {
  119. -        EASSERT(bitmap_isset(&info.attrmask, 0, FATTR4_WORD0_ACL));
  120. -    }
  121.  
  122.      status = InitializeSecurityDescriptor(&sec_desc,
  123.                                            SECURITY_DESCRIPTOR_REVISION);
  124. diff --git a/daemon/getattr.c b/daemon/getattr.c
  125. index 7c8b2d1..7501f39 100644
  126. --- a/daemon/getattr.c
  127. +++ b/daemon/getattr.c
  128. @@ -98,7 +98,7 @@ static int handle_getattr(void *daemon_context, nfs41_upcall *upcall)
  129.      }
  130.  
  131.      if (info.type == NF4LNK) {
  132. -        nfs41_file_info target_info;
  133. +        nfs41_file_info target_info = { 0 };
  134.          int target_status = nfs41_symlink_follow(upcall->root_ref,
  135.              state->session, &state->file, &target_info);
  136.          if (target_status == NO_ERROR) {
  137. diff --git a/daemon/name_cache.c b/daemon/name_cache.c
  138. index 950c188..24b69d6 100644
  139. --- a/daemon/name_cache.c
  140. +++ b/daemon/name_cache.c
  141. @@ -87,11 +87,12 @@ static __inline bool_t is_delegation(
  142.  #define NC_ATTR_NUMLINKS    (1 <<  8)
  143.  #define NC_ATTR_OWNER       (1 <<  9)
  144.  #define NC_ATTR_OWNER_GROUP (1 << 10)
  145. -#define NC_ATTR_TIME_ACCESS (1 << 11)
  146. -#define NC_ATTR_TIME_CREATE (1 << 12)
  147. -#define NC_ATTR_TIME_MODIFY (1 << 13)
  148. -#define NC_ATTR_SYSTEM      (1 << 14)
  149. -#define NC_ATTR_CLONE_BLKSIZE (1 << 15)
  150. +#define NC_ATTR_ACL         (1 << 11)
  151. +#define NC_ATTR_TIME_ACCESS (1 << 12)
  152. +#define NC_ATTR_TIME_CREATE (1 << 13)
  153. +#define NC_ATTR_TIME_MODIFY (1 << 14)
  154. +#define NC_ATTR_SYSTEM      (1 << 15)
  155. +#define NC_ATTR_CLONE_BLKSIZE (1 << 16)
  156.  
  157.  /* attribute cache */
  158.  struct attr_cache_entry {
  159. @@ -123,6 +124,7 @@ struct attr_cache_entry {
  160.      unsigned                delegated : 1;
  161.      char                    owner[NFS4_FATTR4_OWNER_LIMIT+1];
  162.      char                    owner_group[NFS4_FATTR4_OWNER_LIMIT+1];
  163. +    nfsacl41                acl;
  164.  };
  165.  #define ATTR_ENTRY_SIZE sizeof(struct attr_cache_entry)
  166.  
  167. @@ -169,6 +171,7 @@ static int attr_cache_entry_create(
  168.      entry->fsid_minor = 0ULL;
  169.      entry->invalidated = FALSE;
  170.      entry->delegated = FALSE;
  171. +    (void)memset(&entry->acl, 0, sizeof(nfsacl41));
  172.      *entry_out = entry;
  173.  out:
  174.      return status;
  175. @@ -180,6 +183,12 @@ static __inline void attr_cache_entry_free(
  176.  {
  177.      DPRINTF(NCLVL1, ("attr_cache_entry_free(%llu)\n", entry->fileid));
  178.      RB_REMOVE(attr_tree, &cache->head, entry);
  179. +
  180. +    if (entry->acl.aces) {
  181. +        free(entry->acl.aces);
  182. +        entry->acl.aces = NULL;
  183. +    }
  184. +
  185.      /* add it back to free_entries */
  186.      list_add_tail(&cache->free_entries, &entry->free_entry);
  187.  }
  188. @@ -344,6 +353,20 @@ static void attr_cache_update(
  189.              entry->nc_attrs |= NC_ATTR_ARCHIVE;
  190.              entry->archive = info->archive;
  191.          }
  192. +        if (info->attrmask.arr[0] & FATTR4_WORD0_ACL) {
  193. +            if (entry->acl.aces) {
  194. +                free(entry->acl.aces);
  195. +                entry->acl.aces = NULL;
  196. +            }
  197. +
  198. +            entry->nc_attrs &= ~NC_ATTR_ACL;
  199. +
  200. +            if (info->acl) {
  201. +                entry->nc_attrs |= NC_ATTR_ACL;
  202. +                (void)dup_nfsacl41aces(&entry->acl, info->acl);
  203. +                EASSERT(entry->acl.aces != NULL);
  204. +            }
  205. +        }
  206.      }
  207.      if (info->attrmask.count > 1) {
  208.          if (info->attrmask.arr[1] & FATTR4_WORD1_MODE) {
  209. @@ -463,6 +486,18 @@ static void copy_attrs(
  210.          /* this should only happen for newly created files/dirs */
  211.          dst->owner_group = NULL;
  212.      }
  213. +    if (src->nc_attrs & NC_ATTR_ACL) {
  214. +        /*
  215. +         * Only copy attribute if |dst| provides a pointer to an ACL struct
  216. +         * This implicitly solves the issue who will free |dst->acl.aces|,
  217. +         * because only who provides a |dst->acl| will get ACL/ACE data,
  218. +         * but then also has to free the |dst->acl.aces| data.
  219. +         */
  220. +        if (dst->acl) {
  221. +            dst->attrmask.arr[0] |= FATTR4_WORD0_ACL;
  222. +            (void)dup_nfsacl41aces(dst->acl, &src->acl);
  223. +        }
  224. +    }
  225.      if (src->nc_attrs & NC_ATTR_FSID) {
  226.          dst->attrmask.arr[0] |= FATTR4_WORD0_FSID;
  227.          dst->fsid.major = src->fsid_major;
  228. diff --git a/daemon/nfs41_ops.c b/daemon/nfs41_ops.c
  229. index 862ce0e..485811b 100644
  230. --- a/daemon/nfs41_ops.c
  231. +++ b/daemon/nfs41_ops.c
  232. @@ -1478,28 +1478,31 @@ int nfs41_setattr(
  233.  
  234.      nfs41_superblock_getattr_mask(file->fh.superblock, &attr_request);
  235.  
  236. -    if (info->attrmask.count >= 2) {
  237. -        /*
  238. -         * If we set owner and/or owner_group make sure we ask
  239. -         * the server to send the values back for two reasons:
  240. -         * 1, Handle cases like "all_squash" (e.g. nfsd turns
  241. -         * owner/owner_group always into "nobody"/"nogroup")
  242. -         * 2. Make sure we update the name cache with the new
  243. -         * owner/owner_group
  244. -         *
  245. -         * Note that this can be a bit tricky as we might pass
  246. -         * a "name@domain" string to the server, but get a numeric
  247. -         * uid/gid as strings back, which means the name cache
  248. -         * might have both representations.
  249. -         */
  250. -        if (info->attrmask.arr[1] & FATTR4_WORD1_OWNER) {
  251. -            attr_request.count = 2;
  252. -            attr_request.arr[1] |= FATTR4_WORD1_OWNER;
  253. -        }
  254. -        if (info->attrmask.arr[1] & FATTR4_WORD1_OWNER_GROUP) {
  255. -            attr_request.count = 2;
  256. -            attr_request.arr[1] |= FATTR4_WORD1_OWNER_GROUP;
  257. -        }
  258. +    /*
  259. +     * If we set owner, owner_group and/or ACLs make sure we ask
  260. +     * the server to send the values back for two reasons:
  261. +     * 1, Handle cases like "all_squash" (e.g. nfsd turns
  262. +     * owner/owner_group always into "nobody"/"nogroup")
  263. +     * 2. Make sure we update the name cache with the new
  264. +     * owner/owner_group/ACLs
  265. +     *
  266. +     * Note that this can be a bit tricky as we might pass
  267. +     * a "name@domain" string to the server, but get a numeric
  268. +     * uid/gid as strings back, which means the name cache
  269. +     * might have both representations.
  270. +     */
  271. +    if (bitmap_isset(&info->attrmask, 1, FATTR4_WORD1_OWNER)) {
  272. +        attr_request.count = 2;
  273. +        attr_request.arr[1] |= FATTR4_WORD1_OWNER;
  274. +    }
  275. +    if (bitmap_isset(&info->attrmask, 1, FATTR4_WORD1_OWNER_GROUP)) {
  276. +        attr_request.count = 2;
  277. +        attr_request.arr[1] |= FATTR4_WORD1_OWNER_GROUP;
  278. +    }
  279. +    if (bitmap_isset(&info->attrmask, 0, FATTR4_WORD0_ACL)) {
  280. +        if (attr_request.count == 0)
  281. +            attr_request.count = 1;
  282. +        attr_request.arr[0] |= FATTR4_WORD0_ACL;
  283.      }
  284.  
  285.      compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res);
  286. diff --git a/daemon/readdir.c b/daemon/readdir.c
  287. index f3564bf..5282cd3 100644
  288. --- a/daemon/readdir.c
  289. +++ b/daemon/readdir.c
  290. @@ -515,7 +515,7 @@ static int lookup_symlink(
  291.  {
  292.      nfs41_abs_path path;
  293.      nfs41_path_fh file;
  294. -    nfs41_file_info info;
  295. +    nfs41_file_info info = { 0 };
  296.      int status;
  297.  
  298.      status = format_abs_path(parent->path, name, &path);
  299. diff --git a/daemon/util.c b/daemon/util.c
  300. index 3a56b7c..4d396c1 100644
  301. --- a/daemon/util.c
  302. +++ b/daemon/util.c
  303. @@ -638,3 +638,22 @@ bool getwinntversionnnumbers(
  304.      return false;
  305.  #endif /* _WIN64 */
  306.  }
  307. +
  308. +bool dup_nfsacl41aces(
  309. +    nfsacl41 *restrict out_acl,
  310. +    const nfsacl41 *restrict in_acl)
  311. +{
  312. +    size_t acemem_size = in_acl->count * sizeof(nfsace4);
  313. +
  314. +    out_acl->aces = malloc(acemem_size);
  315. +    if (out_acl->aces == NULL) {
  316. +        free(out_acl);
  317. +        return false;
  318. +    }
  319. +
  320. +    out_acl->count = in_acl->count;
  321. +    out_acl->flag = in_acl->flag;
  322. +    (void)memcpy(out_acl->aces, in_acl->aces, acemem_size);
  323. +
  324. +    return true;
  325. +}
  326. diff --git a/daemon/util.h b/daemon/util.h
  327. index 011d411..d4f5c2c 100644
  328. --- a/daemon/util.h
  329. +++ b/daemon/util.h
  330. @@ -364,4 +364,6 @@ bool_t waitcriticalsection(LPCRITICAL_SECTION cs);
  331.  
  332.  bool getwinntversionnnumbers(DWORD *MajorVersionPtr, DWORD *MinorVersionPtr, DWORD *BuildNumberPtr);
  333.  
  334. +bool dup_nfsacl41aces(nfsacl41 *restrict out_acl, const nfsacl41 *restrict in_acl);
  335. +
  336.  #endif /* !__NFS41_DAEMON_UTIL_H__ */
  337. diff --git a/tests/sparsefiles/multisparsefiletest.ksh b/tests/sparsefiles/multisparsefiletest.ksh
  338. index b62f577..d6cdf8a 100644
  339. --- a/tests/sparsefiles/multisparsefiletest.ksh
  340. +++ b/tests/sparsefiles/multisparsefiletest.ksh
  341. @@ -329,7 +329,7 @@ builtin wc
  342.  # - verify file sizes (original vs copy/clone)
  343.  # - tests for sparse files >= 2GB, 4GB, 16GB
  344.  #
  345. -typeset test_cloning=false
  346. +typeset test_cloning=true
  347.  
  348.  multisparsefiletest1

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.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at