Import from CS git
This commit is contained in:
parent
c713474ed8
commit
18eb69dd2d
208
SOURCES/nfs-utils-2.3.3-gssd-do-not-use-krb5_cc_initialize.patch
Normal file
208
SOURCES/nfs-utils-2.3.3-gssd-do-not-use-krb5_cc_initialize.patch
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
From ad4eafccd244e87af315c432d076b4f988dde52a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Olga Kornievskaia <okorniev@redhat.com>
|
||||||
|
Date: Mon, 24 Mar 2025 08:43:43 -0400
|
||||||
|
Subject: [PATCH 2/2] gssd: do not use krb5_cc_initialize
|
||||||
|
|
||||||
|
Note: This patch differs from the upstream version in several places
|
||||||
|
because RHEL 8 does not have c8659457 ("gssd: We never use the nocache
|
||||||
|
param of gssd_check_if_cc_exists()") or f066f87b ("gssd: enable forcing
|
||||||
|
cred renewal using the keytab").
|
||||||
|
|
||||||
|
Original commit message:
|
||||||
|
|
||||||
|
When gssd refreshes machine credentials, it uses the
|
||||||
|
krb5_get_init_creds_keytab() and then to save the received credentials
|
||||||
|
in a ticket cache, it proceeds to initialize the credential cache via
|
||||||
|
a krb5_cc_initialize() before storing the received credentials into it.
|
||||||
|
|
||||||
|
krb5_cc_initialize() is not concurrency safe. two gssd upcalls by
|
||||||
|
uid=0, one for krb5i auth flavor and another for krb5p, would enter
|
||||||
|
into krb5_cc_initialize() and one of them would fail, leading to
|
||||||
|
an upcall failure and NFS operation error.
|
||||||
|
|
||||||
|
Instead it was proposed that gssd changes its design to do what
|
||||||
|
kinit does and forgo the use of krb5_cc_initialize and instead setup
|
||||||
|
the output cache via krb5_get_init_creds_opt_set_out_cache() prior
|
||||||
|
to calling krb5_get_init_creds_keytab() which would then store
|
||||||
|
credentials automatically.
|
||||||
|
|
||||||
|
https://mailman.mit.edu/pipermail/krbdev/2025-February/013708.html
|
||||||
|
|
||||||
|
Signed-off-by: Olga Kornievskaia <okorniev@redhat.com>
|
||||||
|
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||||
|
(cherry picked from commit 1cd9e3c0d290646e80750249914396566dd6b800)
|
||||||
|
Signed-off-by: Scott Mayhew <smayhew@redhat.com>
|
||||||
|
---
|
||||||
|
utils/gssd/krb5_util.c | 103 ++++++++++++++++++++---------------------
|
||||||
|
1 file changed, 50 insertions(+), 53 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
|
||||||
|
index 871add74..43bc8744 100644
|
||||||
|
--- a/utils/gssd/krb5_util.c
|
||||||
|
+++ b/utils/gssd/krb5_util.c
|
||||||
|
@@ -161,7 +161,8 @@ static int select_krb5_ccache(const struct dirent *d);
|
||||||
|
static int gssd_find_existing_krb5_ccache(uid_t uid, char *dirname,
|
||||||
|
const char **cctype, struct dirent **d);
|
||||||
|
static int gssd_get_single_krb5_cred(krb5_context context,
|
||||||
|
- krb5_keytab kt, struct gssd_k5_kt_princ *ple, int nocache);
|
||||||
|
+ krb5_keytab kt, struct gssd_k5_kt_princ *ple, int nocache,
|
||||||
|
+ krb5_ccache ccache);
|
||||||
|
static int query_krb5_ccache(const char* cred_cache, char **ret_princname,
|
||||||
|
char **ret_realm);
|
||||||
|
|
||||||
|
@@ -368,16 +369,14 @@ static int
|
||||||
|
gssd_get_single_krb5_cred(krb5_context context,
|
||||||
|
krb5_keytab kt,
|
||||||
|
struct gssd_k5_kt_princ *ple,
|
||||||
|
- int nocache)
|
||||||
|
+ int nocache,
|
||||||
|
+ krb5_ccache ccache)
|
||||||
|
{
|
||||||
|
krb5_get_init_creds_opt *opts = NULL;
|
||||||
|
krb5_creds my_creds;
|
||||||
|
- krb5_ccache ccache = NULL;
|
||||||
|
char kt_name[BUFSIZ];
|
||||||
|
- char cc_name[BUFSIZ];
|
||||||
|
int code;
|
||||||
|
time_t now = time(0);
|
||||||
|
- char *cache_type;
|
||||||
|
char *pname = NULL;
|
||||||
|
char *k5err = NULL;
|
||||||
|
pthread_t tid = pthread_self();
|
||||||
|
@@ -427,6 +426,14 @@ gssd_get_single_krb5_cred(krb5_context context,
|
||||||
|
krb5_get_init_creds_opt_set_tkt_life(opts, 5*60);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+ if ((code = krb5_get_init_creds_opt_set_out_ccache(context, opts,
|
||||||
|
+ ccache))) {
|
||||||
|
+ k5err = gssd_k5_err_msg(context, code);
|
||||||
|
+ printerr(1, "WARNING: %s while initializing ccache for "
|
||||||
|
+ "principal '%s' using keytab '%s'\n", k5err,
|
||||||
|
+ pname ? pname : "<unparsable>", kt_name);
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
if ((code = krb5_get_init_creds_keytab(context, &my_creds, ple->princ,
|
||||||
|
kt, 0, NULL, opts))) {
|
||||||
|
k5err = gssd_k5_err_msg(context, code);
|
||||||
|
@@ -436,61 +443,18 @@ gssd_get_single_krb5_cred(krb5_context context,
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * Initialize cache file which we're going to be using
|
||||||
|
- */
|
||||||
|
-
|
||||||
|
pthread_mutex_lock(&ple_lock);
|
||||||
|
- if (use_memcache)
|
||||||
|
- cache_type = "MEMORY";
|
||||||
|
- else
|
||||||
|
- cache_type = "FILE";
|
||||||
|
- snprintf(cc_name, sizeof(cc_name), "%s:%s/%s%s_%s",
|
||||||
|
- cache_type,
|
||||||
|
- ccachesearch[0], GSSD_DEFAULT_CRED_PREFIX,
|
||||||
|
- GSSD_DEFAULT_MACHINE_CRED_SUFFIX, ple->realm);
|
||||||
|
ple->endtime = my_creds.times.endtime;
|
||||||
|
- if (ple->ccname == NULL || strcmp(ple->ccname, cc_name) != 0) {
|
||||||
|
- free(ple->ccname);
|
||||||
|
- ple->ccname = strdup(cc_name);
|
||||||
|
- if (ple->ccname == NULL) {
|
||||||
|
- printerr(0, "ERROR: no storage to duplicate credentials "
|
||||||
|
- "cache name '%s'\n", cc_name);
|
||||||
|
- code = ENOMEM;
|
||||||
|
- pthread_mutex_unlock(&ple_lock);
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
pthread_mutex_unlock(&ple_lock);
|
||||||
|
- if ((code = krb5_cc_resolve(context, cc_name, &ccache))) {
|
||||||
|
- k5err = gssd_k5_err_msg(context, code);
|
||||||
|
- printerr(0, "ERROR: %s while opening credential cache '%s'\n",
|
||||||
|
- k5err, cc_name);
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
- if ((code = krb5_cc_initialize(context, ccache, ple->princ))) {
|
||||||
|
- k5err = gssd_k5_err_msg(context, code);
|
||||||
|
- printerr(0, "ERROR: %s while initializing credential "
|
||||||
|
- "cache '%s'\n", k5err, cc_name);
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
- if ((code = krb5_cc_store_cred(context, ccache, &my_creds))) {
|
||||||
|
- k5err = gssd_k5_err_msg(context, code);
|
||||||
|
- printerr(0, "ERROR: %s while storing credentials in '%s'\n",
|
||||||
|
- k5err, cc_name);
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
|
||||||
|
code = 0;
|
||||||
|
- printerr(2, "%s(0x%lx): principal '%s' ccache:'%s'\n",
|
||||||
|
- __func__, tid, pname, cc_name);
|
||||||
|
+ printerr(2, "%s(0x%lx): principal '%s' ccache:'%s'\n",
|
||||||
|
+ __func__, tid, pname, ple->ccname);
|
||||||
|
out:
|
||||||
|
if (opts)
|
||||||
|
krb5_get_init_creds_opt_free(context, opts);
|
||||||
|
if (pname)
|
||||||
|
k5_free_unparsed_name(context, pname);
|
||||||
|
- if (ccache)
|
||||||
|
- krb5_cc_close(context, ccache);
|
||||||
|
krb5_free_cred_contents(context, &my_creds);
|
||||||
|
krb5_free_string(context, k5err);
|
||||||
|
return (code);
|
||||||
|
@@ -1108,10 +1072,12 @@ gssd_refresh_krb5_machine_credential_internal(char *hostname,
|
||||||
|
{
|
||||||
|
krb5_error_code code = 0;
|
||||||
|
krb5_context context;
|
||||||
|
- krb5_keytab kt = NULL;;
|
||||||
|
+ krb5_keytab kt = NULL;
|
||||||
|
+ krb5_ccache ccache = NULL;
|
||||||
|
int retval = 0;
|
||||||
|
- char *k5err = NULL;
|
||||||
|
+ char *k5err = NULL, *cache_type;
|
||||||
|
const char *svcnames[] = { "$", "root", "nfs", "host", NULL };
|
||||||
|
+ char cc_name[BUFSIZ];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If a specific service name was specified, use it.
|
||||||
|
@@ -1170,7 +1136,38 @@ gssd_refresh_krb5_machine_credential_internal(char *hostname,
|
||||||
|
goto out_free_kt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- retval = gssd_get_single_krb5_cred(context, kt, ple, 0);
|
||||||
|
+
|
||||||
|
+ if (use_memcache)
|
||||||
|
+ cache_type = "MEMORY";
|
||||||
|
+ else
|
||||||
|
+ cache_type = "FILE";
|
||||||
|
+ snprintf(cc_name, sizeof(cc_name), "%s:%s/%s%s_%s",
|
||||||
|
+ cache_type,
|
||||||
|
+ ccachesearch[0], GSSD_DEFAULT_CRED_PREFIX,
|
||||||
|
+ GSSD_DEFAULT_MACHINE_CRED_SUFFIX, ple->realm);
|
||||||
|
+
|
||||||
|
+ pthread_mutex_lock(&ple_lock);
|
||||||
|
+ if (ple->ccname == NULL || strcmp(ple->ccname, cc_name) != 0) {
|
||||||
|
+ free(ple->ccname);
|
||||||
|
+ ple->ccname = strdup(cc_name);
|
||||||
|
+ if (ple->ccname == NULL) {
|
||||||
|
+ printerr(0, "ERROR: no storage to duplicate credentials "
|
||||||
|
+ "cache name '%s'\n", cc_name);
|
||||||
|
+ code = ENOMEM;
|
||||||
|
+ pthread_mutex_unlock(&ple_lock);
|
||||||
|
+ goto out_free_kt;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ pthread_mutex_unlock(&ple_lock);
|
||||||
|
+ if ((code = krb5_cc_resolve(context, cc_name, &ccache))) {
|
||||||
|
+ k5err = gssd_k5_err_msg(context, code);
|
||||||
|
+ printerr(0, "ERROR: %s while opening credential cache '%s'\n",
|
||||||
|
+ k5err, cc_name);
|
||||||
|
+ goto out_free_kt;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ retval = gssd_get_single_krb5_cred(context, kt, ple, 0, ccache);
|
||||||
|
+ krb5_cc_close(context, ccache);
|
||||||
|
out_free_kt:
|
||||||
|
krb5_kt_close(context, kt);
|
||||||
|
out_free_context:
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
@ -0,0 +1,47 @@
|
|||||||
|
From 7511a77fc7eb7bd3ae38fcf54d49a47c25c3ed50 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Scott Mayhew <smayhew@redhat.com>
|
||||||
|
Date: Mon, 24 Mar 2025 08:59:24 -0400
|
||||||
|
Subject: [nfs-utils PATCH] gssd.man: add documentation for use-gss-proxy
|
||||||
|
nfs.conf option
|
||||||
|
|
||||||
|
Signed-off-by: Scott Mayhew <smayhew@redhat.com>
|
||||||
|
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||||
|
---
|
||||||
|
utils/gssd/gssd.man | 14 +++++++++++++-
|
||||||
|
1 file changed, 13 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/utils/gssd/gssd.man b/utils/gssd/gssd.man
|
||||||
|
index c735eff6..4a75b056 100644
|
||||||
|
--- a/utils/gssd/gssd.man
|
||||||
|
+++ b/utils/gssd/gssd.man
|
||||||
|
@@ -392,6 +392,17 @@ Setting to
|
||||||
|
is equivalent to providing the
|
||||||
|
.B -H
|
||||||
|
flag.
|
||||||
|
+.TP
|
||||||
|
+.B use-gss-proxy
|
||||||
|
+Setting this to 1 allows
|
||||||
|
+.BR gssproxy (8)
|
||||||
|
+to intercept GSSAPI calls and service them on behalf of
|
||||||
|
+.BR rpc.gssd ,
|
||||||
|
+enabling certain features such as keytab-based client initiation.
|
||||||
|
+Note that this is unrelated to the functionality that
|
||||||
|
+.BR gssproxy (8)
|
||||||
|
+provides on behalf of the NFS server. For more information, see
|
||||||
|
+.BR https://github.com/gssapi/gssproxy/blob/main/docs/NFS.md#nfs-client .
|
||||||
|
.P
|
||||||
|
In addtion, the following value is recognized from the
|
||||||
|
.B [general]
|
||||||
|
@@ -405,7 +416,8 @@ Equivalent to
|
||||||
|
.BR rpc.svcgssd (8),
|
||||||
|
.BR kerberos (1),
|
||||||
|
.BR kinit (1),
|
||||||
|
-.BR krb5.conf (5)
|
||||||
|
+.BR krb5.conf (5),
|
||||||
|
+.BR gssproxy (8)
|
||||||
|
.SH AUTHORS
|
||||||
|
.br
|
||||||
|
Dug Song <dugsong@umich.edu>
|
||||||
|
--
|
||||||
|
2.48.1
|
||||||
|
|
@ -0,0 +1,98 @@
|
|||||||
|
From 55d9bf151b100db9bf52e8f968e33f3ae1d234f5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Olga Kornievskaia <okorniev@redhat.com>
|
||||||
|
Date: Mon, 24 Mar 2025 08:40:32 -0400
|
||||||
|
Subject: [PATCH 1/2] gssd: unconditionally use krb5_get_init_creds_opt_alloc
|
||||||
|
|
||||||
|
Note: This patch has a context difference from the upstream version
|
||||||
|
because RHEL 8 does not have c8659457 ("gssd: We never use the nocache
|
||||||
|
param of gssd_check_if_cc_exists()") or f066f87b ("gssd: enable forcing
|
||||||
|
cred renewal using the keytab").
|
||||||
|
|
||||||
|
Original commit message:
|
||||||
|
|
||||||
|
Modern kerberos API uses krb5_get_init_creds_opt_alloc() for managing
|
||||||
|
its options for credential data structure.
|
||||||
|
|
||||||
|
Signed-off-by: Olga Kornievskaia <okorniev@redhat.com>
|
||||||
|
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||||
|
(cherry picked from commit 9b3f949331c6541a358fc28bac323533f94d7e0b)
|
||||||
|
Signed-off-by: Scott Mayhew <smayhew@redhat.com>
|
||||||
|
---
|
||||||
|
utils/gssd/krb5_util.c | 37 ++++++++++---------------------------
|
||||||
|
1 file changed, 10 insertions(+), 27 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
|
||||||
|
index a1a77a2f..871add74 100644
|
||||||
|
--- a/utils/gssd/krb5_util.c
|
||||||
|
+++ b/utils/gssd/krb5_util.c
|
||||||
|
@@ -370,12 +370,7 @@ gssd_get_single_krb5_cred(krb5_context context,
|
||||||
|
struct gssd_k5_kt_princ *ple,
|
||||||
|
int nocache)
|
||||||
|
{
|
||||||
|
-#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS
|
||||||
|
- krb5_get_init_creds_opt *init_opts = NULL;
|
||||||
|
-#else
|
||||||
|
- krb5_get_init_creds_opt options;
|
||||||
|
-#endif
|
||||||
|
- krb5_get_init_creds_opt *opts;
|
||||||
|
+ krb5_get_init_creds_opt *opts = NULL;
|
||||||
|
krb5_creds my_creds;
|
||||||
|
krb5_ccache ccache = NULL;
|
||||||
|
char kt_name[BUFSIZ];
|
||||||
|
@@ -413,33 +408,23 @@ gssd_get_single_krb5_cred(krb5_context context,
|
||||||
|
if ((krb5_unparse_name(context, ple->princ, &pname)))
|
||||||
|
pname = NULL;
|
||||||
|
|
||||||
|
-#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS
|
||||||
|
- code = krb5_get_init_creds_opt_alloc(context, &init_opts);
|
||||||
|
+ code = krb5_get_init_creds_opt_alloc(context, &opts);
|
||||||
|
if (code) {
|
||||||
|
k5err = gssd_k5_err_msg(context, code);
|
||||||
|
printerr(0, "ERROR: %s allocating gic options\n", k5err);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
- if (krb5_get_init_creds_opt_set_addressless(context, init_opts, 1))
|
||||||
|
+#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS
|
||||||
|
+ if (krb5_get_init_creds_opt_set_addressless(context, opts, 1))
|
||||||
|
printerr(1, "WARNING: Unable to set option for addressless "
|
||||||
|
"tickets. May have problems behind a NAT.\n");
|
||||||
|
-#ifdef TEST_SHORT_LIFETIME
|
||||||
|
- /* set a short lifetime (for debugging only!) */
|
||||||
|
- printerr(1, "WARNING: Using (debug) short machine cred lifetime!\n");
|
||||||
|
- krb5_get_init_creds_opt_set_tkt_life(init_opts, 5*60);
|
||||||
|
+#else
|
||||||
|
+ krb5_get_init_creds_opt_set_address_list(opts, NULL);
|
||||||
|
#endif
|
||||||
|
- opts = init_opts;
|
||||||
|
-
|
||||||
|
-#else /* HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS */
|
||||||
|
-
|
||||||
|
- krb5_get_init_creds_opt_init(&options);
|
||||||
|
- krb5_get_init_creds_opt_set_address_list(&options, NULL);
|
||||||
|
#ifdef TEST_SHORT_LIFETIME
|
||||||
|
/* set a short lifetime (for debugging only!) */
|
||||||
|
- printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n");
|
||||||
|
- krb5_get_init_creds_opt_set_tkt_life(&options, 5*60);
|
||||||
|
-#endif
|
||||||
|
- opts = &options;
|
||||||
|
+ printerr(1, "WARNING: Using (debug) short machine cred lifetime!\n");
|
||||||
|
+ krb5_get_init_creds_opt_set_tkt_life(opts, 5*60);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((code = krb5_get_init_creds_keytab(context, &my_creds, ple->princ,
|
||||||
|
@@ -500,10 +485,8 @@ gssd_get_single_krb5_cred(krb5_context context,
|
||||||
|
printerr(2, "%s(0x%lx): principal '%s' ccache:'%s'\n",
|
||||||
|
__func__, tid, pname, cc_name);
|
||||||
|
out:
|
||||||
|
-#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS
|
||||||
|
- if (init_opts)
|
||||||
|
- krb5_get_init_creds_opt_free(context, init_opts);
|
||||||
|
-#endif
|
||||||
|
+ if (opts)
|
||||||
|
+ krb5_get_init_creds_opt_free(context, opts);
|
||||||
|
if (pname)
|
||||||
|
k5_free_unparsed_name(context, pname);
|
||||||
|
if (ccache)
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
141
SOURCES/nfs-utils-2.3.3-mountstats-fixes.patch
Normal file
141
SOURCES/nfs-utils-2.3.3-mountstats-fixes.patch
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
diff --git a/tools/mountstats/mountstats.py b/tools/mountstats/mountstats.py
|
||||||
|
index 8e129c83..d488f9e1 100755
|
||||||
|
--- a/tools/mountstats/mountstats.py
|
||||||
|
+++ b/tools/mountstats/mountstats.py
|
||||||
|
@@ -333,6 +333,11 @@ class DeviceData:
|
||||||
|
found = True
|
||||||
|
self.__parse_rpc_line(words)
|
||||||
|
|
||||||
|
+ def fstype(self):
|
||||||
|
+ """Return the fstype for the mountpoint
|
||||||
|
+ """
|
||||||
|
+ return self.__nfs_data['fstype']
|
||||||
|
+
|
||||||
|
def is_nfs_mountpoint(self):
|
||||||
|
"""Return True if this is an NFS or NFSv4 mountpoint,
|
||||||
|
otherwise return False
|
||||||
|
@@ -953,73 +958,78 @@ def nfsstat_command(args):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def print_iostat_summary(old, new, devices, time):
|
||||||
|
+ if len(devices) == 0:
|
||||||
|
+ print('No NFS mount points were found')
|
||||||
|
+ return
|
||||||
|
+
|
||||||
|
for device in devices:
|
||||||
|
stats = DeviceData()
|
||||||
|
stats.parse_stats(new[device])
|
||||||
|
- if not old or device not in old:
|
||||||
|
+ if old and device in old:
|
||||||
|
+ old_stats = DeviceData()
|
||||||
|
+ old_stats.parse_stats(old[device])
|
||||||
|
+ if stats.fstype() == old_stats.fstype():
|
||||||
|
+ stats.compare_iostats(old_stats).display_iostats(time)
|
||||||
|
+ else: # device is in old, but fstypes are different
|
||||||
|
+ stats.display_iostats(time)
|
||||||
|
+ else: # device is only in new
|
||||||
|
stats.display_iostats(time)
|
||||||
|
- else:
|
||||||
|
- if ("fstype autofs" not in str(old[device])) and ("fstype autofs" not in str(new[device])):
|
||||||
|
- old_stats = DeviceData()
|
||||||
|
- old_stats.parse_stats(old[device])
|
||||||
|
- diff_stats = stats.compare_iostats(old_stats)
|
||||||
|
- diff_stats.display_iostats(time)
|
||||||
|
+
|
||||||
|
+def list_nfs_mounts(givenlist, mountstats):
|
||||||
|
+ """return a list of NFS mounts given a list to validate or
|
||||||
|
+ return a full list if the given list is empty -
|
||||||
|
+ may return an empty list if none found
|
||||||
|
+ """
|
||||||
|
+ devicelist = []
|
||||||
|
+ if len(givenlist) > 0:
|
||||||
|
+ for device in givenlist:
|
||||||
|
+ if device in mountstats:
|
||||||
|
+ stats = DeviceData()
|
||||||
|
+ stats.parse_stats(mountstats[device])
|
||||||
|
+ if stats.is_nfs_mountpoint():
|
||||||
|
+ devicelist += [device]
|
||||||
|
+ else:
|
||||||
|
+ for device, descr in mountstats.items():
|
||||||
|
+ stats = DeviceData()
|
||||||
|
+ stats.parse_stats(descr)
|
||||||
|
+ if stats.is_nfs_mountpoint():
|
||||||
|
+ devicelist += [device]
|
||||||
|
+ return devicelist
|
||||||
|
|
||||||
|
def iostat_command(args):
|
||||||
|
"""iostat-like command for NFS mount points
|
||||||
|
"""
|
||||||
|
mountstats = parse_stats_file(args.infile)
|
||||||
|
- devices = [os.path.normpath(mp) for mp in args.mountpoints]
|
||||||
|
+ origdevices = [os.path.normpath(mp) for mp in args.mountpoints]
|
||||||
|
|
||||||
|
if args.since:
|
||||||
|
old_mountstats = parse_stats_file(args.since)
|
||||||
|
else:
|
||||||
|
old_mountstats = None
|
||||||
|
|
||||||
|
- # make certain devices contains only NFS mount points
|
||||||
|
- if len(devices) > 0:
|
||||||
|
- check = []
|
||||||
|
- for device in devices:
|
||||||
|
- stats = DeviceData()
|
||||||
|
- try:
|
||||||
|
- stats.parse_stats(mountstats[device])
|
||||||
|
- if stats.is_nfs_mountpoint():
|
||||||
|
- check += [device]
|
||||||
|
- except KeyError:
|
||||||
|
- continue
|
||||||
|
- devices = check
|
||||||
|
- else:
|
||||||
|
- for device, descr in mountstats.items():
|
||||||
|
- stats = DeviceData()
|
||||||
|
- stats.parse_stats(descr)
|
||||||
|
- if stats.is_nfs_mountpoint():
|
||||||
|
- devices += [device]
|
||||||
|
- if len(devices) == 0:
|
||||||
|
- print('No NFS mount points were found')
|
||||||
|
- return 1
|
||||||
|
-
|
||||||
|
sample_time = 0
|
||||||
|
|
||||||
|
+ # make certain devices contains only NFS mount points
|
||||||
|
+ devices = list_nfs_mounts(origdevices, mountstats)
|
||||||
|
+ print_iostat_summary(old_mountstats, mountstats, devices, sample_time)
|
||||||
|
+
|
||||||
|
if args.interval is None:
|
||||||
|
- print_iostat_summary(old_mountstats, mountstats, devices, sample_time)
|
||||||
|
return
|
||||||
|
|
||||||
|
- if args.count is not None:
|
||||||
|
- count = args.count
|
||||||
|
- while count != 0:
|
||||||
|
- print_iostat_summary(old_mountstats, mountstats, devices, sample_time)
|
||||||
|
- old_mountstats = mountstats
|
||||||
|
- time.sleep(args.interval)
|
||||||
|
- sample_time = args.interval
|
||||||
|
- mountstats = parse_stats_file(args.infile)
|
||||||
|
+ count = args.count
|
||||||
|
+ while True:
|
||||||
|
+ if count is not None:
|
||||||
|
count -= 1
|
||||||
|
- else:
|
||||||
|
- while True:
|
||||||
|
- print_iostat_summary(old_mountstats, mountstats, devices, sample_time)
|
||||||
|
- old_mountstats = mountstats
|
||||||
|
- time.sleep(args.interval)
|
||||||
|
- sample_time = args.interval
|
||||||
|
- mountstats = parse_stats_file(args.infile)
|
||||||
|
+ if count == 0:
|
||||||
|
+ break
|
||||||
|
+ time.sleep(args.interval)
|
||||||
|
+ old_mountstats = mountstats
|
||||||
|
+ sample_time = args.interval
|
||||||
|
+ mountstats = parse_stats_file(args.infile)
|
||||||
|
+ # nfs mountpoints may appear or disappear, so we need to
|
||||||
|
+ # recheck the devices list each time we parse mountstats
|
||||||
|
+ devices = list_nfs_mounts(origdevices, mountstats)
|
||||||
|
+ print_iostat_summary(old_mountstats, mountstats, devices, sample_time)
|
||||||
|
|
||||||
|
args.infile.close()
|
||||||
|
if args.since:
|
47
SOURCES/nfs-utils-2.3.3-nfs-man-rdirplus.patch
Normal file
47
SOURCES/nfs-utils-2.3.3-nfs-man-rdirplus.patch
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
From 3cca9dbeab3b159c27c1dc48e791139744baf6d0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Coddington <bcodding@redhat.com>
|
||||||
|
Date: Mon, 24 Mar 2025 15:47:43 -0400
|
||||||
|
Subject: [nfs-utils PATCH] nfs(5): Add new rdirplus functionality, clarify
|
||||||
|
|
||||||
|
The proposed kernel [patch][1] will modify the rdirplus mount option to
|
||||||
|
accept optional string values of "none" and "force". Update the man page
|
||||||
|
to reflect these changes and clarify the current client's behavior for the
|
||||||
|
default.
|
||||||
|
|
||||||
|
[1]: https://lore.kernel.org/linux-nfs/8c33cd92be52255b0dd0a7489c9e5cc35434ec95.1741876784.git.bcodding@redhat.com/T/#u
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
|
||||||
|
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||||
|
---
|
||||||
|
utils/mount/nfs.man | 15 ++++++++++-----
|
||||||
|
1 file changed, 10 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/utils/mount/nfs.man b/utils/mount/nfs.man
|
||||||
|
index b5c5913b..94dc29d4 100644
|
||||||
|
--- a/utils/mount/nfs.man
|
||||||
|
+++ b/utils/mount/nfs.man
|
||||||
|
@@ -434,11 +434,16 @@ option may also be used by some pNFS drivers to decide how many
|
||||||
|
connections to set up to the data servers.
|
||||||
|
.TP 1.5i
|
||||||
|
.BR rdirplus " / " nordirplus
|
||||||
|
-Selects whether to use NFS v3 or v4 READDIRPLUS requests.
|
||||||
|
-If this option is not specified, the NFS client uses READDIRPLUS requests
|
||||||
|
-on NFS v3 or v4 mounts to read small directories.
|
||||||
|
-Some applications perform better if the client uses only READDIR requests
|
||||||
|
-for all directories.
|
||||||
|
+Selects whether to use NFS v3 or v4 READDIRPLUS requests. If this option is
|
||||||
|
+not specified, the NFS client uses a heuristic to optimize performance by
|
||||||
|
+choosing READDIR vs READDIRPLUS based on how often the calling process uses
|
||||||
|
+the additional attributes returned from READDIRPLUS. Some applications
|
||||||
|
+perform better if the client uses only READDIR requests for all directories.
|
||||||
|
+.TP 1.5i
|
||||||
|
+.BR rdirplus={none|force}
|
||||||
|
+If set to "force", the NFS client always attempts to use READDIRPLUS
|
||||||
|
+requests. If set to "none", the behavior is the same as
|
||||||
|
+.B nordirplus.
|
||||||
|
.TP 1.5i
|
||||||
|
.BI retry= n
|
||||||
|
The number of minutes that the
|
||||||
|
--
|
||||||
|
2.48.1
|
||||||
|
|
242
SOURCES/nfs-utils-2.3.3-nfsiostat-fixes.patch
Normal file
242
SOURCES/nfs-utils-2.3.3-nfsiostat-fixes.patch
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
26f8410d mountstats/nfsiostat: merge and rework the infinite and counted loops
|
||||||
|
21238e5c mountstats/nfsiostat: Move the checks for empty mountpoint list into the print function
|
||||||
|
1bd30a9d nfsiostat: make comment explain mount/unmount more broadly
|
||||||
|
2b9251ed nfsiostat: fix crash when filtering mountstats after unmount
|
||||||
|
9836adbc nfsiostat: mirror how mountstats iostat prints the stats
|
||||||
|
936a19cc mountstats/nfsiostat: add a function to return the fstype
|
||||||
|
155c5343 nfsiostat: skip argv[0] when parsing command-line
|
||||||
|
39f57998 nfsiostat/mountstats: handle KeyError in compare_iostats()
|
||||||
|
c4c14011 nfsiostat: replace 'list' reserved word
|
||||||
|
|
||||||
|
diff --git a/tools/nfs-iostat/nfs-iostat.py b/tools/nfs-iostat/nfs-iostat.py
|
||||||
|
index 7cbe543c..dec0e861 100644
|
||||||
|
--- a/tools/nfs-iostat/nfs-iostat.py
|
||||||
|
+++ b/tools/nfs-iostat/nfs-iostat.py
|
||||||
|
@@ -493,20 +493,20 @@ def list_nfs_mounts(givenlist, mountstats):
|
||||||
|
return a full list if the given list is empty -
|
||||||
|
may return an empty list if none found
|
||||||
|
"""
|
||||||
|
- list = []
|
||||||
|
+ devicelist = []
|
||||||
|
if len(givenlist) > 0:
|
||||||
|
for device in givenlist:
|
||||||
|
stats = DeviceData()
|
||||||
|
stats.parse_stats(mountstats[device])
|
||||||
|
if stats.is_nfs_mountpoint():
|
||||||
|
- list += [device]
|
||||||
|
+ devicelist += [device]
|
||||||
|
else:
|
||||||
|
for device, descr in mountstats.items():
|
||||||
|
stats = DeviceData()
|
||||||
|
stats.parse_stats(descr)
|
||||||
|
if stats.is_nfs_mountpoint():
|
||||||
|
- list += [device]
|
||||||
|
- return list
|
||||||
|
+ devicelist += [device]
|
||||||
|
+ return devicelist
|
||||||
|
|
||||||
|
def iostat_command(name):
|
||||||
|
"""iostat-like command for NFS mount points
|
||||||
|
diff --git a/tools/mountstats/mountstats.py b/tools/mountstats/mountstats.py
|
||||||
|
index 014f38a3..1054f698 100755
|
||||||
|
--- a/tools/mountstats/mountstats.py
|
||||||
|
+++ b/tools/mountstats/mountstats.py
|
||||||
|
@@ -560,7 +560,10 @@ class DeviceData:
|
||||||
|
# the reference to them. so we build new lists here
|
||||||
|
# for the result object.
|
||||||
|
for op in result.__rpc_data['ops']:
|
||||||
|
- result.__rpc_data[op] = list(map(difference, self.__rpc_data[op], old_stats.__rpc_data[op]))
|
||||||
|
+ try:
|
||||||
|
+ result.__rpc_data[op] = list(map(difference, self.__rpc_data[op], old_stats.__rpc_data[op]))
|
||||||
|
+ except KeyError:
|
||||||
|
+ continue
|
||||||
|
|
||||||
|
# update the remaining keys
|
||||||
|
if protocol == 'udp':
|
||||||
|
diff --git a/tools/nfs-iostat/nfs-iostat.py b/tools/nfs-iostat/nfs-iostat.py
|
||||||
|
index b7e98a2a..5556f692 100755
|
||||||
|
--- a/tools/nfs-iostat/nfs-iostat.py
|
||||||
|
+++ b/tools/nfs-iostat/nfs-iostat.py
|
||||||
|
@@ -213,8 +213,11 @@ class DeviceData:
|
||||||
|
# the reference to them. so we build new lists here
|
||||||
|
# for the result object.
|
||||||
|
for op in result.__rpc_data['ops']:
|
||||||
|
- result.__rpc_data[op] = list(map(
|
||||||
|
- difference, self.__rpc_data[op], old_stats.__rpc_data[op]))
|
||||||
|
+ try:
|
||||||
|
+ result.__rpc_data[op] = list(map(
|
||||||
|
+ difference, self.__rpc_data[op], old_stats.__rpc_data[op]))
|
||||||
|
+ except KeyError:
|
||||||
|
+ continue
|
||||||
|
|
||||||
|
# update the remaining keys we care about
|
||||||
|
result.__rpc_data['rpcsends'] -= old_stats.__rpc_data['rpcsends']
|
||||||
|
diff --git a/tools/nfs-iostat/nfs-iostat.py b/tools/nfs-iostat/nfs-iostat.py
|
||||||
|
index 85294fb9..e46b1a83 100755
|
||||||
|
--- a/tools/nfs-iostat/nfs-iostat.py
|
||||||
|
+++ b/tools/nfs-iostat/nfs-iostat.py
|
||||||
|
@@ -187,6 +187,11 @@ class DeviceData:
|
||||||
|
found = True
|
||||||
|
self.__parse_rpc_line(words)
|
||||||
|
|
||||||
|
+ def fstype(self):
|
||||||
|
+ """Return the fstype for the mountpoint
|
||||||
|
+ """
|
||||||
|
+ return self.__nfs_data['fstype']
|
||||||
|
+
|
||||||
|
def is_nfs_mountpoint(self):
|
||||||
|
"""Return True if this is an NFS or NFSv4 mountpoint,
|
||||||
|
otherwise return False
|
||||||
|
@@ -471,41 +476,31 @@ def parse_stats_file(filename):
|
||||||
|
return ms_dict
|
||||||
|
|
||||||
|
def print_iostat_summary(old, new, devices, time, options):
|
||||||
|
- stats = {}
|
||||||
|
- diff_stats = {}
|
||||||
|
- devicelist = []
|
||||||
|
- if old:
|
||||||
|
- # Trim device list to only include intersection of old and new data,
|
||||||
|
- # this addresses umounts due to autofs mountpoints
|
||||||
|
- for device in devices:
|
||||||
|
- if "fstype autofs" not in str(old[device]):
|
||||||
|
- devicelist.append(device)
|
||||||
|
- else:
|
||||||
|
- devicelist = devices
|
||||||
|
+ display_stats = {}
|
||||||
|
+
|
||||||
|
+ if len(devices) == 0:
|
||||||
|
+ print('No NFS mount points were found')
|
||||||
|
+ return
|
||||||
|
|
||||||
|
- for device in devicelist:
|
||||||
|
- stats[device] = DeviceData()
|
||||||
|
- stats[device].parse_stats(new[device])
|
||||||
|
- if old:
|
||||||
|
+ for device in devices:
|
||||||
|
+ stats = DeviceData()
|
||||||
|
+ stats.parse_stats(new[device])
|
||||||
|
+ if old and device in old:
|
||||||
|
old_stats = DeviceData()
|
||||||
|
old_stats.parse_stats(old[device])
|
||||||
|
- diff_stats[device] = stats[device].compare_iostats(old_stats)
|
||||||
|
+ if stats.fstype() == old_stats.fstype():
|
||||||
|
+ display_stats[device] = stats.compare_iostats(old_stats)
|
||||||
|
+ else: # device is in old, but fstypes are different
|
||||||
|
+ display_stats[device] = stats
|
||||||
|
+ else: # device is only in new
|
||||||
|
+ display_stats[device] = stats
|
||||||
|
|
||||||
|
if options.sort:
|
||||||
|
- if old:
|
||||||
|
- # We now have compared data and can print a comparison
|
||||||
|
- # ordered by mountpoint ops per second
|
||||||
|
- devicelist.sort(key=lambda x: diff_stats[x].ops(time), reverse=True)
|
||||||
|
- else:
|
||||||
|
- # First iteration, just sort by newly parsed ops/s
|
||||||
|
- devicelist.sort(key=lambda x: stats[x].ops(time), reverse=True)
|
||||||
|
+ devices.sort(key=lambda x: display_stats[x].ops(time), reverse=True)
|
||||||
|
|
||||||
|
count = 1
|
||||||
|
- for device in devicelist:
|
||||||
|
- if old:
|
||||||
|
- diff_stats[device].display_iostats(time, options.which)
|
||||||
|
- else:
|
||||||
|
- stats[device].display_iostats(time, options.which)
|
||||||
|
+ for device in devices:
|
||||||
|
+ display_stats[device].display_iostats(time, options.which)
|
||||||
|
|
||||||
|
count += 1
|
||||||
|
if (count > options.list):
|
||||||
|
@@ -520,10 +515,11 @@ def list_nfs_mounts(givenlist, mountstats):
|
||||||
|
devicelist = []
|
||||||
|
if len(givenlist) > 0:
|
||||||
|
for device in givenlist:
|
||||||
|
- stats = DeviceData()
|
||||||
|
- stats.parse_stats(mountstats[device])
|
||||||
|
- if stats.is_nfs_mountpoint():
|
||||||
|
- devicelist += [device]
|
||||||
|
+ if device in mountstats:
|
||||||
|
+ stats = DeviceData()
|
||||||
|
+ stats.parse_stats(mountstats[device])
|
||||||
|
+ if stats.is_nfs_mountpoint():
|
||||||
|
+ devicelist += [device]
|
||||||
|
else:
|
||||||
|
for device, descr in mountstats.items():
|
||||||
|
stats = DeviceData()
|
||||||
|
@@ -592,11 +588,7 @@ client are listed.
|
||||||
|
parser.add_option_group(displaygroup)
|
||||||
|
|
||||||
|
(options, args) = parser.parse_args(sys.argv)
|
||||||
|
- for arg in args:
|
||||||
|
-
|
||||||
|
- if arg == sys.argv[0]:
|
||||||
|
- continue
|
||||||
|
-
|
||||||
|
+ for arg in args[1:]:
|
||||||
|
if arg in mountstats:
|
||||||
|
origdevices += [arg]
|
||||||
|
elif not interval_seen:
|
||||||
|
@@ -622,47 +614,29 @@ client are listed.
|
||||||
|
print('Illegal <count> value %s' % arg)
|
||||||
|
return
|
||||||
|
|
||||||
|
- # make certain devices contains only NFS mount points
|
||||||
|
- devices = list_nfs_mounts(origdevices, mountstats)
|
||||||
|
- if len(devices) == 0:
|
||||||
|
- print('No NFS mount points were found')
|
||||||
|
- return
|
||||||
|
-
|
||||||
|
-
|
||||||
|
old_mountstats = None
|
||||||
|
sample_time = 0.0
|
||||||
|
|
||||||
|
+ # make certain devices contains only NFS mount points
|
||||||
|
+ devices = list_nfs_mounts(origdevices, mountstats)
|
||||||
|
+ print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options)
|
||||||
|
+
|
||||||
|
if not interval_seen:
|
||||||
|
- print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options)
|
||||||
|
return
|
||||||
|
|
||||||
|
- if count_seen:
|
||||||
|
- while count != 0:
|
||||||
|
- print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options)
|
||||||
|
- old_mountstats = mountstats
|
||||||
|
- time.sleep(interval)
|
||||||
|
- sample_time = interval
|
||||||
|
- mountstats = parse_stats_file('/proc/self/mountstats')
|
||||||
|
- # automount mountpoints add and drop, if automount is involved
|
||||||
|
- # we need to recheck the devices list when reparsing
|
||||||
|
- devices = list_nfs_mounts(origdevices,mountstats)
|
||||||
|
- if len(devices) == 0:
|
||||||
|
- print('No NFS mount points were found')
|
||||||
|
- return
|
||||||
|
+ while True:
|
||||||
|
+ if count_seen:
|
||||||
|
count -= 1
|
||||||
|
- else:
|
||||||
|
- while True:
|
||||||
|
- print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options)
|
||||||
|
- old_mountstats = mountstats
|
||||||
|
- time.sleep(interval)
|
||||||
|
- sample_time = interval
|
||||||
|
- mountstats = parse_stats_file('/proc/self/mountstats')
|
||||||
|
- # automount mountpoints add and drop, if automount is involved
|
||||||
|
- # we need to recheck the devices list when reparsing
|
||||||
|
- devices = list_nfs_mounts(origdevices,mountstats)
|
||||||
|
- if len(devices) == 0:
|
||||||
|
- print('No NFS mount points were found')
|
||||||
|
- return
|
||||||
|
+ if count == 0:
|
||||||
|
+ break
|
||||||
|
+ time.sleep(interval)
|
||||||
|
+ old_mountstats = mountstats
|
||||||
|
+ sample_time = interval
|
||||||
|
+ mountstats = parse_stats_file('/proc/self/mountstats')
|
||||||
|
+ # nfs mountpoints may appear or disappear, so we need to
|
||||||
|
+ # recheck the devices list each time we parse mountstats
|
||||||
|
+ devices = list_nfs_mounts(origdevices, mountstats)
|
||||||
|
+ print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Main
|
@ -2,7 +2,7 @@ Summary: NFS utilities and supporting clients and daemons for the kernel NFS ser
|
|||||||
Name: nfs-utils
|
Name: nfs-utils
|
||||||
URL: http://linux-nfs.org/
|
URL: http://linux-nfs.org/
|
||||||
Version: 2.3.3
|
Version: 2.3.3
|
||||||
Release: 59%{?dist}
|
Release: 64%{?dist}
|
||||||
Epoch: 1
|
Epoch: 1
|
||||||
|
|
||||||
# group all 32bit related archs
|
# group all 32bit related archs
|
||||||
@ -109,6 +109,16 @@ Patch055: nfs-utils-2.3.3-systemd-rpcstatd.patch
|
|||||||
Patch056: nfs-utils-2.3.3-mountd-v4clnts.patch
|
Patch056: nfs-utils-2.3.3-mountd-v4clnts.patch
|
||||||
Patch057: nfs-utils-2.3.3-covscan-return-value.patch
|
Patch057: nfs-utils-2.3.3-covscan-return-value.patch
|
||||||
|
|
||||||
|
#
|
||||||
|
# RHEL 8.10.z
|
||||||
|
#
|
||||||
|
Patch058: nfs-utils-2.3.3-gssd-man-document-use-gss-proxy.patch
|
||||||
|
Patch059: nfs-utils-2.3.3-gssd-unconditionally-use-krb5_get_init_creds_opt_all.patch
|
||||||
|
Patch060: nfs-utils-2.3.3-gssd-do-not-use-krb5_cc_initialize.patch
|
||||||
|
Patch061: nfs-utils-2.3.3-nfsiostat-fixes.patch
|
||||||
|
Patch062: nfs-utils-2.3.3-mountstats-fixes.patch
|
||||||
|
Patch063: nfs-utils-2.3.3-nfs-man-rdirplus.patch
|
||||||
|
|
||||||
Patch100: nfs-utils-1.2.1-statdpath-man.patch
|
Patch100: nfs-utils-1.2.1-statdpath-man.patch
|
||||||
Patch101: nfs-utils-1.2.1-exp-subtree-warn-off.patch
|
Patch101: nfs-utils-1.2.1-exp-subtree-warn-off.patch
|
||||||
Patch102: nfs-utils-2.3.3-idmap-errmsg.patch
|
Patch102: nfs-utils-2.3.3-idmap-errmsg.patch
|
||||||
@ -386,6 +396,22 @@ fi
|
|||||||
%{_libdir}/libnfsidmap.so
|
%{_libdir}/libnfsidmap.so
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Tue May 20 2025 Scott Mayhew <smayhew@redhat.com> 2.3.3-64
|
||||||
|
- update rdirplus documentation on nfs(5) man page (RHEL-91253)
|
||||||
|
|
||||||
|
* Fri May 9 2025 Scott Mayhew <smayhew@redhat.com> 2.3.3-63
|
||||||
|
- mountstats fixes (RHEL-90242)
|
||||||
|
|
||||||
|
* Thu May 8 2025 Scott Mayhew <smayhew@redhat.com> 2.3.3-62
|
||||||
|
- nfsiostat fixes (RHEL-90242)
|
||||||
|
|
||||||
|
* Mon Apr 28 2025 Scott Mayhew <smayhew@redhat.com> 2.3.3-61
|
||||||
|
- gssd: unconditionally use krb5_get_init_creds_opt_alloc (RHEL-62422)
|
||||||
|
- gssd: do not use krb5_cc_initialize (RHEL-62422)
|
||||||
|
|
||||||
|
* Tue Apr 15 2025 Scott Mayhew <smayhew@redhat.com> 2.3.3-60
|
||||||
|
- gssd.man: add documentation for use-gss-proxy (RHEL-13085)
|
||||||
|
|
||||||
* Thu Jan 12 2023 Steve Dickson <steved@redhat.com> 2.3.3-59
|
* Thu Jan 12 2023 Steve Dickson <steved@redhat.com> 2.3.3-59
|
||||||
- Covscan Scan: Wrong Check of Return Value (bz 2151966)
|
- Covscan Scan: Wrong Check of Return Value (bz 2151966)
|
||||||
- Covscan Scan: Clang (experimental) (bz 2151971)
|
- Covscan Scan: Clang (experimental) (bz 2151971)
|
||||||
|
Loading…
Reference in New Issue
Block a user