[PATCH v2 1/3] nss: Introduce dedicated struct nss_database_for_fork type

Sam James sam@gentoo.org
Mon Feb 9 19:38:28 GMT 2026


Florian Weimer <fweimer@redhat.com> writes:

> The initialized field in struct nss_database_data is rather confusing
> because it is not used by the regular NSS code, only by the fork
> state synchronization code.  Introduce a separate type and place
> the initialized field there.

Reviewed-by: Sam James <sam@gentoo.org>

> ---
>  nss/nss_database.c | 14 +++++++-------
>  nss/nss_database.h | 12 +++++++++---
>  posix/fork.c       |  2 +-
>  3 files changed, 17 insertions(+), 11 deletions(-)
>
> diff --git a/nss/nss_database.c b/nss/nss_database.c
> index 6997b5bb04..19e752ef65 100644
> --- a/nss/nss_database.c
> +++ b/nss/nss_database.c
> @@ -56,7 +56,6 @@ global_state_allocate (void *closure)
>      {
>        result->data.nsswitch_conf.size = -1; /* Force reload.  */
>        memset (result->data.services, 0, sizeof (result->data.services));
> -      result->data.initialized = true;
>        result->data.reload_disabled = false;
>        __libc_lock_init (result->lock);
>        result->root_ino = 0;
> @@ -439,8 +438,8 @@ nss_database_check_reload_and_get (struct nss_database_state *local,
>    /* Avoid overwriting the global configuration until we have loaded
>       everything successfully.  Otherwise, if the file change
>       information changes back to what is in the global configuration,
> -     the lookups would use the partially-written  configuration.  */
> -  struct nss_database_data staging = { .initialized = true, };
> +     the lookups would use the partially-written configuration.  */
> +  struct nss_database_data staging = { };
>  
>    bool ok = nss_database_reload (&staging, &initial);
>  
> @@ -491,7 +490,7 @@ __nss_database_freeres (void)
>  }
>  
>  void
> -__nss_database_fork_prepare_parent (struct nss_database_data *data)
> +__nss_database_fork_prepare_parent (struct nss_database_for_fork *data)
>  {
>    /* Do not use allocate_once to trigger loading unnecessarily.  */
>    struct nss_database_state *local = atomic_load_acquire (&global_database_state);
> @@ -503,20 +502,21 @@ __nss_database_fork_prepare_parent (struct nss_database_data *data)
>           because it avoids acquiring the lock during the actual
>           fork.  */
>        __libc_lock_lock (local->lock);
> -      *data = local->data;
> +      data->data = local->data;
>        __libc_lock_unlock (local->lock);
> +      data->initialized = true;
>      }
>  }
>  
>  void
> -__nss_database_fork_subprocess (struct nss_database_data *data)
> +__nss_database_fork_subprocess (struct nss_database_for_fork *data)
>  {
>    struct nss_database_state *local = atomic_load_acquire (&global_database_state);
>    if (data->initialized)
>      {
>        /* Restore the state at the point of the fork.  */
>        assert (local != NULL);
> -      local->data = *data;
> +      local->data = data->data;
>        __libc_lock_init (local->lock);
>      }
>    else if (local != NULL)
> diff --git a/nss/nss_database.h b/nss/nss_database.h
> index 1f2ff1639a..a4f3369eb0 100644
> --- a/nss/nss_database.h
> +++ b/nss/nss_database.h
> @@ -70,15 +70,21 @@ struct nss_database_data
>    struct file_change_detection nsswitch_conf;
>    nss_action_list services[NSS_DATABASE_COUNT];
>    int reload_disabled;          /* Actually bool; int for atomic access.  */
> -  bool initialized;
> +};
> +
> +/* Use to store a consistent state snapshot across fork.  */
> +struct nss_database_for_fork
> +{
> +  bool initialized;  /* Set to true if the data field below is initialized.  */
> +  struct nss_database_data data;
>  };
>  
>  /* Called by fork in the parent process, before forking.  */
> -void __nss_database_fork_prepare_parent (struct nss_database_data *data)
> +void __nss_database_fork_prepare_parent (struct nss_database_for_fork *)
>    attribute_hidden;
>  
>  /* Called by fork in the new subprocess, after forking.  */
> -void __nss_database_fork_subprocess (struct nss_database_data *data)
> +void __nss_database_fork_subprocess (struct nss_database_for_fork *)
>    attribute_hidden;
>  
>  #endif /* _NSS_DATABASE_H */
> diff --git a/posix/fork.c b/posix/fork.c
> index 8e541ff985..933ac6fee7 100644
> --- a/posix/fork.c
> +++ b/posix/fork.c
> @@ -50,7 +50,7 @@ __libc_fork (void)
>  
>    lastrun = __run_prefork_handlers (multiple_threads);
>  
> -  struct nss_database_data nss_database_data;
> +  struct nss_database_for_fork nss_database_data;
>  
>    /* If we are not running multiple threads, we do not have to
>       preserve lock state.  If fork runs from a signal handler, only
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 418 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20260209/14cc50ad/attachment.sig>


More information about the Libc-alpha mailing list