Compare commits
10 Commits
imports/c8
...
c8
Author | SHA1 | Date | |
---|---|---|---|
18eb69dd2d | |||
|
c713474ed8 | ||
|
6d474dfbc4 | ||
|
944240a27c | ||
|
d551f79e6d | ||
|
39bd9e53dd | ||
|
0507dd6161 | ||
|
b7b45d88ad | ||
|
1292498303 | ||
|
f3288b818c |
@ -1,12 +0,0 @@
|
|||||||
diff -up nfs-utils-2.1.1/utils/nfsidmap/nfsidmap.c.orig nfs-utils-2.1.1/utils/nfsidmap/nfsidmap.c
|
|
||||||
--- nfs-utils-2.1.1/utils/nfsidmap/nfsidmap.c.orig 2017-01-12 10:21:39.000000000 -0500
|
|
||||||
+++ nfs-utils-2.1.1/utils/nfsidmap/nfsidmap.c 2017-04-26 12:47:56.715133443 -0400
|
|
||||||
@@ -432,7 +432,7 @@ int main(int argc, char **argv)
|
|
||||||
|
|
||||||
xlog_stderr(verbose);
|
|
||||||
if ((argc - optind) != 2) {
|
|
||||||
- xlog_warn("Bad arg count. Check /etc/request-key.conf");
|
|
||||||
+ xlog_err("Bad arg count. Check /etc/request-key.d/request-key.conf");
|
|
||||||
xlog_warn(usage, progname);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
@ -1,9 +1,9 @@
|
|||||||
diff -up nfs-utils-2.3.1/systemd/nfs-server.service.orig nfs-utils-2.3.1/systemd/nfs-server.service
|
diff -up nfs-utils-2.3.3/systemd/nfs-server.service.orig nfs-utils-2.3.3/systemd/nfs-server.service
|
||||||
--- nfs-utils-2.3.1/systemd/nfs-server.service.orig 2018-01-19 10:25:38.153513857 -0500
|
--- nfs-utils-2.3.3/systemd/nfs-server.service.orig 2020-12-11 09:05:23.499222371 -0500
|
||||||
+++ nfs-utils-2.3.1/systemd/nfs-server.service 2018-01-19 10:30:52.977245126 -0500
|
+++ nfs-utils-2.3.3/systemd/nfs-server.service 2020-12-11 09:06:38.970186395 -0500
|
||||||
@@ -26,6 +26,7 @@ Type=oneshot
|
@@ -23,6 +23,7 @@ Type=oneshot
|
||||||
RemainAfterExit=yes
|
RemainAfterExit=yes
|
||||||
ExecStartPre=/usr/sbin/exportfs -r
|
ExecStartPre=-/usr/sbin/exportfs -r
|
||||||
ExecStart=/usr/sbin/rpc.nfsd
|
ExecStart=/usr/sbin/rpc.nfsd
|
||||||
+ExecStart=-/bin/sh -c 'if systemctl -q is-active gssproxy; then systemctl reload gssproxy ; fi'
|
+ExecStart=-/bin/sh -c 'if systemctl -q is-active gssproxy; then systemctl reload gssproxy ; fi'
|
||||||
ExecStop=/usr/sbin/rpc.nfsd 0
|
ExecStop=/usr/sbin/rpc.nfsd 0
|
||||||
|
25
SOURCES/nfs-utils-2.3.3-covscan-return-value.patch
Normal file
25
SOURCES/nfs-utils-2.3.3-covscan-return-value.patch
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
diff -up nfs-utils-2.3.3/support/export/client.c.orig nfs-utils-2.3.3/support/export/client.c
|
||||||
|
--- nfs-utils-2.3.3/support/export/client.c.orig 2018-09-06 14:09:08.000000000 -0400
|
||||||
|
+++ nfs-utils-2.3.3/support/export/client.c 2023-01-12 08:59:44.171609492 -0500
|
||||||
|
@@ -689,6 +689,9 @@ check_netgroup(const nfs_client *clp, co
|
||||||
|
|
||||||
|
/* check whether the IP itself is in the netgroup */
|
||||||
|
ip = calloc(INET6_ADDRSTRLEN, 1);
|
||||||
|
+ if (ip == NULL)
|
||||||
|
+ goto out;
|
||||||
|
+
|
||||||
|
if (inet_ntop(ai->ai_family, &(((struct sockaddr_in *)ai->ai_addr)->sin_addr), ip, INET6_ADDRSTRLEN) == ip) {
|
||||||
|
if (innetgr(netgroup, ip, NULL, NULL)) {
|
||||||
|
free(hname);
|
||||||
|
diff -up nfs-utils-2.3.3/tools/nfsrahead/main.c.orig nfs-utils-2.3.3/tools/nfsrahead/main.c
|
||||||
|
--- nfs-utils-2.3.3/tools/nfsrahead/main.c.orig 2023-01-12 08:58:28.297466979 -0500
|
||||||
|
+++ nfs-utils-2.3.3/tools/nfsrahead/main.c 2023-01-12 09:00:37.988419866 -0500
|
||||||
|
@@ -167,7 +167,7 @@ int main(int argc, char **argv)
|
||||||
|
if ((ret = get_device_info(argv[optind], &device)) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
- if (ret != 0) {
|
||||||
|
+ if (ret != 0 || device.fstype == NULL) {
|
||||||
|
xlog(D_GENERAL, "unable to find device %s\n", argv[optind]);
|
||||||
|
goto out;
|
||||||
|
}
|
50
SOURCES/nfs-utils-2.3.3-exportfs-man-labels.patch
Normal file
50
SOURCES/nfs-utils-2.3.3-exportfs-man-labels.patch
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
commit 7d5dcd2358df55353eed94a0e84b77bb3597634e
|
||||||
|
Author: J. Bruce Fields <bfields@redhat.com>
|
||||||
|
Date: Fri Mar 27 13:11:28 2020 -0400
|
||||||
|
|
||||||
|
exports man page: warn about subdirectory exports
|
||||||
|
|
||||||
|
Subdirectory exports have a number of problems which have been poorly
|
||||||
|
documented.
|
||||||
|
|
||||||
|
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
|
||||||
|
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/utils/exportfs/exports.man b/utils/exportfs/exports.man
|
||||||
|
index e3a16f6b..1d171849 100644
|
||||||
|
--- a/utils/exportfs/exports.man
|
||||||
|
+++ b/utils/exportfs/exports.man
|
||||||
|
@@ -494,6 +494,33 @@ export entry for
|
||||||
|
.B /home/joe
|
||||||
|
in the example section below, which maps all requests to uid 150 (which
|
||||||
|
is supposedly that of user joe).
|
||||||
|
+
|
||||||
|
+.SS Subdirectory Exports
|
||||||
|
+
|
||||||
|
+Normally you should only export only the root of a filesystem. The NFS
|
||||||
|
+server will also allow you to export a subdirectory of a filesystem,
|
||||||
|
+however, this has drawbacks:
|
||||||
|
+
|
||||||
|
+First, it may be possible for a malicious user to access files on the
|
||||||
|
+filesystem outside of the exported subdirectory, by guessing filehandles
|
||||||
|
+for those other files. The only way to prevent this is by using the
|
||||||
|
+.IR no_subtree_check
|
||||||
|
+option, which can cause other problems.
|
||||||
|
+
|
||||||
|
+Second, export options may not be enforced in the way that you would
|
||||||
|
+expect. For example, the
|
||||||
|
+.IR security_label
|
||||||
|
+option will not work on subdirectory exports, and if nested subdirectory
|
||||||
|
+exports change the
|
||||||
|
+.IR security_label
|
||||||
|
+or
|
||||||
|
+.IR sec=
|
||||||
|
+options, NFSv4 clients will normally see only the options on the parent
|
||||||
|
+export. Also, where security options differ, a malicious client may use
|
||||||
|
+filehandle-guessing attacks to access the files from one subdirectory
|
||||||
|
+using the options from another.
|
||||||
|
+
|
||||||
|
+
|
||||||
|
.SS Extra Export Tables
|
||||||
|
After reading
|
||||||
|
.I /etc/exports
|
43
SOURCES/nfs-utils-2.3.3-exportfs-root.patch
Normal file
43
SOURCES/nfs-utils-2.3.3-exportfs-root.patch
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
commit ac266e2edc4f40eef810d52c72657b645e4010db
|
||||||
|
Author: Ondrej Mosnacek <omosnace@redhat.com>
|
||||||
|
Date: Tue Apr 6 15:57:37 2021 -0400
|
||||||
|
|
||||||
|
exportfs: fix unexporting of '/'
|
||||||
|
|
||||||
|
The code that has been added to strip trailing slashes from path in
|
||||||
|
unexportfs_parsed() forgot to account for the case of the root
|
||||||
|
directory, which is simply '/'. In that case it accesses path[-1] and
|
||||||
|
reduces the path to an empty string, which then fails to match any
|
||||||
|
export.
|
||||||
|
|
||||||
|
Fix it by stopping the stripping when the path is just a single
|
||||||
|
character - it doesn't matter if it's a '/' or not, we want to keep it
|
||||||
|
either way in that case.
|
||||||
|
|
||||||
|
Reproducer:
|
||||||
|
|
||||||
|
exportfs localhost:/
|
||||||
|
exportfs -u localhost:/
|
||||||
|
|
||||||
|
Without this patch, the unexport step fails with "exportfs: Could not
|
||||||
|
find 'localhost:/' to unexport."
|
||||||
|
|
||||||
|
Fixes: a9a7728d8743 ("exportfs: Deal with path's trailing "/" in unexportfs_parsed()")
|
||||||
|
Link: https://bugzilla.redhat.com/show_bug.cgi?id=1941171
|
||||||
|
|
||||||
|
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
|
||||||
|
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c
|
||||||
|
index 262dd19a..25d757d8 100644
|
||||||
|
--- a/utils/exportfs/exportfs.c
|
||||||
|
+++ b/utils/exportfs/exportfs.c
|
||||||
|
@@ -383,7 +383,7 @@ unexportfs_parsed(char *hname, char *path, int verbose)
|
||||||
|
* so need to deal with it.
|
||||||
|
*/
|
||||||
|
size_t nlen = strlen(path);
|
||||||
|
- while (path[nlen - 1] == '/')
|
||||||
|
+ while ((nlen > 1) && (path[nlen - 1] == '/'))
|
||||||
|
nlen--;
|
||||||
|
|
||||||
|
for (exp = exportlist[htype].p_head; exp; exp = exp->m_next) {
|
30
SOURCES/nfs-utils-2.3.3-exports-manpage-outdated.patch
Normal file
30
SOURCES/nfs-utils-2.3.3-exports-manpage-outdated.patch
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
commit ba90d61be3abca5a699765ce08759ca6b986781d
|
||||||
|
Author: Steve Dickson <steved@redhat.com>
|
||||||
|
Date: Thu Dec 10 14:05:23 2020 -0500
|
||||||
|
|
||||||
|
exports.man: Remove some outdated verbiage
|
||||||
|
|
||||||
|
Years ago, commit 6a7d90cea765 removed the warning
|
||||||
|
this verbiage was talking about, but was never
|
||||||
|
removed from the man page.
|
||||||
|
|
||||||
|
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/utils/exportfs/exports.man b/utils/exportfs/exports.man
|
||||||
|
index 1d171849..54b3f877 100644
|
||||||
|
--- a/utils/exportfs/exports.man
|
||||||
|
+++ b/utils/exportfs/exports.man
|
||||||
|
@@ -169,13 +169,6 @@ default. In all releases after 1.0.0,
|
||||||
|
is the default, and
|
||||||
|
.I async
|
||||||
|
must be explicitly requested if needed.
|
||||||
|
-To help make system administrators aware of this change,
|
||||||
|
-.B exportfs
|
||||||
|
-will issue a warning if neither
|
||||||
|
-.I sync
|
||||||
|
-nor
|
||||||
|
-.I async
|
||||||
|
-is specified.
|
||||||
|
.TP
|
||||||
|
.IR no_wdelay
|
||||||
|
This option has no effect if
|
290
SOURCES/nfs-utils-2.3.3-gssd-debug-cleanup.patch
Normal file
290
SOURCES/nfs-utils-2.3.3-gssd-debug-cleanup.patch
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
diff -up nfs-utils-2.3.3/utils/gssd/err_util.c.orig nfs-utils-2.3.3/utils/gssd/err_util.c
|
||||||
|
--- nfs-utils-2.3.3/utils/gssd/err_util.c.orig 2018-09-06 14:09:08.000000000 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/gssd/err_util.c 2021-07-19 12:29:21.366829573 -0400
|
||||||
|
@@ -70,3 +70,17 @@ int get_verbosity(void)
|
||||||
|
{
|
||||||
|
return verbosity;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+char *
|
||||||
|
+sec2time(int value)
|
||||||
|
+{
|
||||||
|
+ static char buf[BUFSIZ];
|
||||||
|
+ int hr, min, sec;
|
||||||
|
+
|
||||||
|
+ hr = (value / 3600);
|
||||||
|
+ min = (value - (3600*hr))/60;
|
||||||
|
+ sec = (value - (3600*hr) - (min*60));
|
||||||
|
+ sprintf(buf, "%dh:%dm:%ds", hr, min, sec);
|
||||||
|
+ return(buf);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
diff -up nfs-utils-2.3.3/utils/gssd/err_util.h.orig nfs-utils-2.3.3/utils/gssd/err_util.h
|
||||||
|
--- nfs-utils-2.3.3/utils/gssd/err_util.h.orig 2018-09-06 14:09:08.000000000 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/gssd/err_util.h 2021-07-19 12:29:21.367829599 -0400
|
||||||
|
@@ -34,5 +34,6 @@
|
||||||
|
void initerr(char *progname, int verbosity, int fg);
|
||||||
|
void printerr(int priority, char *format, ...);
|
||||||
|
int get_verbosity(void);
|
||||||
|
+char * sec2time(int);
|
||||||
|
|
||||||
|
#endif /* _ERR_UTIL_H_ */
|
||||||
|
diff -up nfs-utils-2.3.3/utils/gssd/gssd.c.orig nfs-utils-2.3.3/utils/gssd/gssd.c
|
||||||
|
--- nfs-utils-2.3.3/utils/gssd/gssd.c.orig 2021-07-19 12:24:13.963644016 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/gssd/gssd.c 2021-07-19 12:29:21.368829626 -0400
|
||||||
|
@@ -396,7 +396,7 @@ gssd_free_client(struct clnt_info *clp)
|
||||||
|
if (refcnt > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
- printerr(3, "freeing client %s\n", clp->relpath);
|
||||||
|
+ printerr(4, "freeing client %s\n", clp->relpath);
|
||||||
|
|
||||||
|
if (clp->krb5_fd >= 0)
|
||||||
|
close(clp->krb5_fd);
|
||||||
|
@@ -417,7 +417,7 @@ gssd_free_client(struct clnt_info *clp)
|
||||||
|
static void
|
||||||
|
gssd_destroy_client(struct clnt_info *clp)
|
||||||
|
{
|
||||||
|
- printerr(3, "destroying client %s\n", clp->relpath);
|
||||||
|
+ printerr(4, "destroying client %s\n", clp->relpath);
|
||||||
|
|
||||||
|
if (clp->krb5_ev) {
|
||||||
|
event_del(clp->krb5_ev);
|
||||||
|
@@ -494,7 +494,7 @@ scan_active_thread_list(void)
|
||||||
|
* upcall_thread_info from the list and free it.
|
||||||
|
*/
|
||||||
|
if (tret == PTHREAD_CANCELED)
|
||||||
|
- printerr(3, "watchdog: thread id 0x%lx cancelled successfully\n",
|
||||||
|
+ printerr(2, "watchdog: thread id 0x%lx cancelled successfully\n",
|
||||||
|
info->tid);
|
||||||
|
saveprev = info->list.tqe_prev;
|
||||||
|
TAILQ_REMOVE(&active_thread_list, info, list);
|
||||||
|
@@ -783,7 +783,7 @@ gssd_scan(void)
|
||||||
|
{
|
||||||
|
struct dirent *d;
|
||||||
|
|
||||||
|
- printerr(3, "doing a full rescan\n");
|
||||||
|
+ printerr(4, "doing a full rescan\n");
|
||||||
|
rewinddir(pipefs_dir);
|
||||||
|
|
||||||
|
while ((d = readdir(pipefs_dir))) {
|
||||||
|
diff -up nfs-utils-2.3.3/utils/gssd/gssd_proc.c.orig nfs-utils-2.3.3/utils/gssd/gssd_proc.c
|
||||||
|
--- nfs-utils-2.3.3/utils/gssd/gssd_proc.c.orig 2021-07-19 12:24:13.964644043 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/gssd/gssd_proc.c 2021-07-19 12:29:21.368829626 -0400
|
||||||
|
@@ -166,8 +166,9 @@ do_downcall(int k5_fd, uid_t uid, struct
|
||||||
|
unsigned int buf_size = 0;
|
||||||
|
pthread_t tid = pthread_self();
|
||||||
|
|
||||||
|
- printerr(2, "do_downcall(0x%x): lifetime_rec=%u acceptor=%.*s\n",
|
||||||
|
- tid, lifetime_rec, acceptor->length, acceptor->value);
|
||||||
|
+ if (get_verbosity() > 1)
|
||||||
|
+ printerr(2, "do_downcall(0x%lx): lifetime_rec=%s acceptor=%.*s\n",
|
||||||
|
+ tid, sec2time(lifetime_rec), acceptor->length, acceptor->value);
|
||||||
|
buf_size = sizeof(uid) + sizeof(timeout) + sizeof(pd->pd_seq_win) +
|
||||||
|
sizeof(pd->pd_ctx_hndl.length) + pd->pd_ctx_hndl.length +
|
||||||
|
sizeof(context_token->length) + context_token->length +
|
||||||
|
@@ -193,7 +194,7 @@ do_downcall(int k5_fd, uid_t uid, struct
|
||||||
|
return;
|
||||||
|
out_err:
|
||||||
|
free(buf);
|
||||||
|
- printerr(1, "do_downcall(0x%x): Failed to write downcall!\n", tid);
|
||||||
|
+ printerr(1, "do_downcall(0x%lx): Failed to write downcall!\n", tid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -204,8 +205,9 @@ do_error_downcall(int k5_fd, uid_t uid,
|
||||||
|
char *p = buf, *end = buf + 1024;
|
||||||
|
unsigned int timeout = 0;
|
||||||
|
int zero = 0;
|
||||||
|
+ pthread_t tid = pthread_self();
|
||||||
|
|
||||||
|
- printerr(2, "doing error downcall\n");
|
||||||
|
+ printerr(2, "do_error_downcall(0x%lx): uid %d err %d\n", tid, uid, err);
|
||||||
|
|
||||||
|
if (WRITE_BYTES(&p, end, uid)) goto out_err;
|
||||||
|
if (WRITE_BYTES(&p, end, timeout)) goto out_err;
|
||||||
|
@@ -328,6 +330,7 @@ create_auth_rpc_client(struct clnt_info
|
||||||
|
struct timeval timeout;
|
||||||
|
struct sockaddr *addr = (struct sockaddr *) &clp->addr;
|
||||||
|
socklen_t salen;
|
||||||
|
+ pthread_t tid = pthread_self();
|
||||||
|
|
||||||
|
sec.qop = GSS_C_QOP_DEFAULT;
|
||||||
|
sec.svc = RPCSEC_GSS_SVC_NONE;
|
||||||
|
@@ -361,8 +364,8 @@ create_auth_rpc_client(struct clnt_info
|
||||||
|
|
||||||
|
/* create an rpc connection to the nfs server */
|
||||||
|
|
||||||
|
- printerr(2, "creating %s client for server %s\n", clp->protocol,
|
||||||
|
- clp->servername);
|
||||||
|
+ printerr(3, "create_auth_rpc_client(0x%lx): creating %s client for server %s\n",
|
||||||
|
+ tid, clp->protocol, clp->servername);
|
||||||
|
|
||||||
|
protocol = IPPROTO_TCP;
|
||||||
|
if ((strcmp(clp->protocol, "udp")) == 0)
|
||||||
|
@@ -405,7 +408,8 @@ create_auth_rpc_client(struct clnt_info
|
||||||
|
if (!tgtname)
|
||||||
|
tgtname = clp->servicename;
|
||||||
|
|
||||||
|
- printerr(2, "creating context with server %s\n", tgtname);
|
||||||
|
+ printerr(3, "create_auth_rpc_client(0x%lx): creating context with server %s\n",
|
||||||
|
+ tid, tgtname);
|
||||||
|
auth = authgss_create_default(rpc_clnt, tgtname, &sec);
|
||||||
|
if (!auth) {
|
||||||
|
/* Our caller should print appropriate message */
|
||||||
|
@@ -507,9 +511,10 @@ krb5_not_machine_creds(struct clnt_info
|
||||||
|
gss_cred_id_t gss_cred;
|
||||||
|
char **dname;
|
||||||
|
int err, resp = -1;
|
||||||
|
+ pthread_t tid = pthread_self();
|
||||||
|
|
||||||
|
- printerr(2, "krb5_not_machine_creds: uid %d tgtname %s\n",
|
||||||
|
- uid, tgtname);
|
||||||
|
+ printerr(2, "krb5_not_machine_creds(0x%lx): uid %d tgtname %s\n",
|
||||||
|
+ tid, uid, tgtname);
|
||||||
|
|
||||||
|
*chg_err = change_identity(uid);
|
||||||
|
if (*chg_err) {
|
||||||
|
@@ -555,9 +560,10 @@ krb5_use_machine_creds(struct clnt_info
|
||||||
|
char **ccname;
|
||||||
|
int nocache = 0;
|
||||||
|
int success = 0;
|
||||||
|
+ pthread_t tid = pthread_self();
|
||||||
|
|
||||||
|
- printerr(2, "krb5_use_machine_creds: uid %d tgtname %s\n",
|
||||||
|
- uid, tgtname);
|
||||||
|
+ printerr(2, "krb5_use_machine_creds(0x%lx): uid %d tgtname %s\n",
|
||||||
|
+ tid, uid, tgtname);
|
||||||
|
|
||||||
|
do {
|
||||||
|
gssd_refresh_krb5_machine_credential(clp->servername,
|
||||||
|
@@ -874,6 +880,7 @@ start_upcall_thread(void (*func)(struct
|
||||||
|
pthread_t th;
|
||||||
|
struct upcall_thread_info *tinfo;
|
||||||
|
int ret;
|
||||||
|
+ pthread_t tid = pthread_self();
|
||||||
|
|
||||||
|
tinfo = alloc_upcall_thread_info();
|
||||||
|
if (!tinfo)
|
||||||
|
@@ -896,6 +903,9 @@ start_upcall_thread(void (*func)(struct
|
||||||
|
free(tinfo);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
+ printerr(2, "start_upcall_thread(0x%lx): created thread id 0x%lx\n",
|
||||||
|
+ tid, th);
|
||||||
|
+
|
||||||
|
tinfo->tid = th;
|
||||||
|
pthread_mutex_lock(&active_thread_list_lock);
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &tinfo->timeout);
|
||||||
|
@@ -958,7 +968,7 @@ handle_gssd_upcall(struct clnt_info *clp
|
||||||
|
}
|
||||||
|
lbuf[lbuflen-1] = 0;
|
||||||
|
|
||||||
|
- printerr(2, "\n%s(0x%x): '%s' (%s)\n", __func__, tid,
|
||||||
|
+ printerr(2, "\n%s(0x%lx): '%s' (%s)\n", __func__, tid,
|
||||||
|
lbuf, clp->relpath);
|
||||||
|
|
||||||
|
for (p = strtok(lbuf, " "); p; p = strtok(NULL, " ")) {
|
||||||
|
diff -up nfs-utils-2.3.3/utils/gssd/krb5_util.c.orig nfs-utils-2.3.3/utils/gssd/krb5_util.c
|
||||||
|
--- nfs-utils-2.3.3/utils/gssd/krb5_util.c.orig 2021-07-19 12:24:13.951643697 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/gssd/krb5_util.c 2021-07-19 12:36:27.746223992 -0400
|
||||||
|
@@ -375,6 +375,7 @@ gssd_get_single_krb5_cred(krb5_context c
|
||||||
|
char *cache_type;
|
||||||
|
char *pname = NULL;
|
||||||
|
char *k5err = NULL;
|
||||||
|
+ pthread_t tid = pthread_self();
|
||||||
|
|
||||||
|
memset(&my_creds, 0, sizeof(my_creds));
|
||||||
|
|
||||||
|
@@ -385,8 +386,8 @@ gssd_get_single_krb5_cred(krb5_context c
|
||||||
|
now += 300;
|
||||||
|
pthread_mutex_lock(&ple_lock);
|
||||||
|
if (ple->ccname && ple->endtime > now && !nocache) {
|
||||||
|
- printerr(3, "INFO: Credentials in CC '%s' are good until %d\n",
|
||||||
|
- ple->ccname, ple->endtime);
|
||||||
|
+ printerr(3, "%s(0x%lx): Credentials in CC '%s' are good until %s",
|
||||||
|
+ __func__, tid, ple->ccname, ctime((time_t *)&ple->endtime));
|
||||||
|
code = 0;
|
||||||
|
pthread_mutex_unlock(&ple_lock);
|
||||||
|
goto out;
|
||||||
|
@@ -486,7 +487,8 @@ gssd_get_single_krb5_cred(krb5_context c
|
||||||
|
}
|
||||||
|
|
||||||
|
code = 0;
|
||||||
|
- printerr(2, "%s: principal '%s' ccache:'%s'\n", __func__, pname, cc_name);
|
||||||
|
+ 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)
|
||||||
|
@@ -615,6 +617,7 @@ get_full_hostname(const char *inhost, ch
|
||||||
|
struct addrinfo hints;
|
||||||
|
int retval;
|
||||||
|
char *c;
|
||||||
|
+ pthread_t tid = pthread_self();
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
@@ -624,8 +627,8 @@ get_full_hostname(const char *inhost, ch
|
||||||
|
/* Get full target hostname */
|
||||||
|
retval = getaddrinfo(inhost, NULL, &hints, &addrs);
|
||||||
|
if (retval) {
|
||||||
|
- printerr(1, "%s while getting full hostname for '%s'\n",
|
||||||
|
- gai_strerror(retval), inhost);
|
||||||
|
+ printerr(1, "%s(0x%lx): getaddrinfo(%s) failed: %s\n",
|
||||||
|
+ __func__, tid, inhost, gai_strerror(retval));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
strncpy(outhost, addrs->ai_canonname, outhostlen);
|
||||||
|
@@ -633,7 +636,10 @@ get_full_hostname(const char *inhost, ch
|
||||||
|
for (c = outhost; *c != '\0'; c++)
|
||||||
|
*c = tolower(*c);
|
||||||
|
|
||||||
|
- printerr(3, "Full hostname for '%s' is '%s'\n", inhost, outhost);
|
||||||
|
+ if (get_verbosity() && strcmp(inhost, outhost))
|
||||||
|
+ printerr(1, "%s(0x%0lx): inhost '%s' different than outhost'%s'\n",
|
||||||
|
+ inhost, outhost);
|
||||||
|
+
|
||||||
|
retval = 0;
|
||||||
|
out:
|
||||||
|
return retval;
|
||||||
|
@@ -819,6 +825,7 @@ find_keytab_entry(krb5_context context,
|
||||||
|
krb5_principal princ;
|
||||||
|
const char *notsetstr = "not set";
|
||||||
|
char *adhostoverride = NULL;
|
||||||
|
+ pthread_t tid = pthread_self();
|
||||||
|
|
||||||
|
|
||||||
|
/* Get full target hostname */
|
||||||
|
@@ -972,7 +979,7 @@ find_keytab_entry(krb5_context context,
|
||||||
|
tried_upper = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
- printerr(2, "Success getting keytab entry for '%s'\n",spn);
|
||||||
|
+ printerr(2, "find_keytab_entry(0x%lx): Success getting keytab entry for '%s'\n",tid, spn);
|
||||||
|
retval = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
@@ -1113,9 +1120,6 @@ gssd_refresh_krb5_machine_credential_int
|
||||||
|
char *k5err = NULL;
|
||||||
|
const char *svcnames[] = { "$", "root", "nfs", "host", NULL };
|
||||||
|
|
||||||
|
- printerr(2, "%s: hostname=%s ple=%p service=%s srchost=%s\n",
|
||||||
|
- __func__, hostname, ple, service, srchost);
|
||||||
|
-
|
||||||
|
/*
|
||||||
|
* If a specific service name was specified, use it.
|
||||||
|
* Otherwise, use the default list.
|
||||||
|
@@ -1124,9 +1128,10 @@ gssd_refresh_krb5_machine_credential_int
|
||||||
|
svcnames[0] = service;
|
||||||
|
svcnames[1] = NULL;
|
||||||
|
}
|
||||||
|
- if (hostname == NULL && ple == NULL)
|
||||||
|
+ if (hostname == NULL && ple == NULL) {
|
||||||
|
+ printerr(0, "ERROR: %s: Invalid args\n", __func__);
|
||||||
|
return EINVAL;
|
||||||
|
-
|
||||||
|
+ }
|
||||||
|
code = krb5_init_context(&context);
|
||||||
|
if (code) {
|
||||||
|
k5err = gssd_k5_err_msg(NULL, code);
|
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
|
||||||
|
|
402
SOURCES/nfs-utils-2.3.3-gssd-failed-thread.patch
Normal file
402
SOURCES/nfs-utils-2.3.3-gssd-failed-thread.patch
Normal file
@ -0,0 +1,402 @@
|
|||||||
|
diff -up nfs-utils-2.3.3/utils/gssd/gssd.c.orig nfs-utils-2.3.3/utils/gssd/gssd.c
|
||||||
|
--- nfs-utils-2.3.3/utils/gssd/gssd.c.orig 2021-07-19 09:39:04.273895536 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/gssd/gssd.c 2021-07-19 09:40:13.942751214 -0400
|
||||||
|
@@ -364,7 +364,7 @@ out:
|
||||||
|
/* Actually frees clp and fields that might be used from other
|
||||||
|
* threads if was last reference.
|
||||||
|
*/
|
||||||
|
-static void
|
||||||
|
+void
|
||||||
|
gssd_free_client(struct clnt_info *clp)
|
||||||
|
{
|
||||||
|
int refcnt;
|
||||||
|
@@ -416,55 +416,6 @@ gssd_destroy_client(struct clnt_info *cl
|
||||||
|
|
||||||
|
static void gssd_scan(void);
|
||||||
|
|
||||||
|
-static int
|
||||||
|
-start_upcall_thread(void (*func)(struct clnt_upcall_info *), void *info)
|
||||||
|
-{
|
||||||
|
- pthread_attr_t attr;
|
||||||
|
- pthread_t th;
|
||||||
|
- int ret;
|
||||||
|
-
|
||||||
|
- ret = pthread_attr_init(&attr);
|
||||||
|
- if (ret != 0) {
|
||||||
|
- printerr(0, "ERROR: failed to init pthread attr: ret %d: %s\n",
|
||||||
|
- ret, strerror(errno));
|
||||||
|
- return ret;
|
||||||
|
- }
|
||||||
|
- ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||||
|
- if (ret != 0) {
|
||||||
|
- printerr(0, "ERROR: failed to create pthread attr: ret %d: "
|
||||||
|
- "%s\n", ret, strerror(errno));
|
||||||
|
- return ret;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- ret = pthread_create(&th, &attr, (void *)func, (void *)info);
|
||||||
|
- if (ret != 0)
|
||||||
|
- printerr(0, "ERROR: pthread_create failed: ret %d: %s\n",
|
||||||
|
- ret, strerror(errno));
|
||||||
|
- return ret;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static struct clnt_upcall_info *alloc_upcall_info(struct clnt_info *clp)
|
||||||
|
-{
|
||||||
|
- struct clnt_upcall_info *info;
|
||||||
|
-
|
||||||
|
- info = malloc(sizeof(struct clnt_upcall_info));
|
||||||
|
- if (info == NULL)
|
||||||
|
- return NULL;
|
||||||
|
-
|
||||||
|
- pthread_mutex_lock(&clp_lock);
|
||||||
|
- clp->refcount++;
|
||||||
|
- pthread_mutex_unlock(&clp_lock);
|
||||||
|
- info->clp = clp;
|
||||||
|
-
|
||||||
|
- return info;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void free_upcall_info(struct clnt_upcall_info *info)
|
||||||
|
-{
|
||||||
|
- gssd_free_client(info->clp);
|
||||||
|
- free(info);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
/* For each upcall read the upcall info into the buffer, then create a
|
||||||
|
* thread in a detached state so that resources are released back into
|
||||||
|
* the system without the need for a join.
|
||||||
|
@@ -473,44 +424,16 @@ static void
|
||||||
|
gssd_clnt_gssd_cb(int UNUSED(fd), short UNUSED(which), void *data)
|
||||||
|
{
|
||||||
|
struct clnt_info *clp = data;
|
||||||
|
- struct clnt_upcall_info *info;
|
||||||
|
-
|
||||||
|
- info = alloc_upcall_info(clp);
|
||||||
|
- if (info == NULL)
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
- info->lbuflen = read(clp->gssd_fd, info->lbuf, sizeof(info->lbuf));
|
||||||
|
- if (info->lbuflen <= 0 || info->lbuf[info->lbuflen-1] != '\n') {
|
||||||
|
- printerr(0, "WARNING: %s: failed reading request\n", __func__);
|
||||||
|
- free_upcall_info(info);
|
||||||
|
- return;
|
||||||
|
- }
|
||||||
|
- info->lbuf[info->lbuflen-1] = 0;
|
||||||
|
|
||||||
|
- if (start_upcall_thread(handle_gssd_upcall, info))
|
||||||
|
- free_upcall_info(info);
|
||||||
|
+ handle_gssd_upcall(clp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gssd_clnt_krb5_cb(int UNUSED(fd), short UNUSED(which), void *data)
|
||||||
|
{
|
||||||
|
struct clnt_info *clp = data;
|
||||||
|
- struct clnt_upcall_info *info;
|
||||||
|
-
|
||||||
|
- info = alloc_upcall_info(clp);
|
||||||
|
- if (info == NULL)
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
- if (read(clp->krb5_fd, &info->uid,
|
||||||
|
- sizeof(info->uid)) < (ssize_t)sizeof(info->uid)) {
|
||||||
|
- printerr(0, "WARNING: %s: failed reading uid from krb5 "
|
||||||
|
- "upcall pipe: %s\n", __func__, strerror(errno));
|
||||||
|
- free_upcall_info(info);
|
||||||
|
- return;
|
||||||
|
- }
|
||||||
|
|
||||||
|
- if (start_upcall_thread(handle_krb5_upcall, info))
|
||||||
|
- free_upcall_info(info);
|
||||||
|
+ handle_krb5_upcall(clp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct clnt_info *
|
||||||
|
diff -up nfs-utils-2.3.3/utils/gssd/gssd.h.orig nfs-utils-2.3.3/utils/gssd/gssd.h
|
||||||
|
--- nfs-utils-2.3.3/utils/gssd/gssd.h.orig 2021-07-19 09:39:04.269895430 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/gssd/gssd.h 2021-07-19 09:40:13.943751240 -0400
|
||||||
|
@@ -84,14 +84,17 @@ struct clnt_info {
|
||||||
|
|
||||||
|
struct clnt_upcall_info {
|
||||||
|
struct clnt_info *clp;
|
||||||
|
- char lbuf[RPC_CHAN_BUF_SIZE];
|
||||||
|
- int lbuflen;
|
||||||
|
uid_t uid;
|
||||||
|
+ int fd;
|
||||||
|
+ char *srchost;
|
||||||
|
+ char *target;
|
||||||
|
+ char *service;
|
||||||
|
};
|
||||||
|
|
||||||
|
-void handle_krb5_upcall(struct clnt_upcall_info *clp);
|
||||||
|
-void handle_gssd_upcall(struct clnt_upcall_info *clp);
|
||||||
|
+void handle_krb5_upcall(struct clnt_info *clp);
|
||||||
|
+void handle_gssd_upcall(struct clnt_info *clp);
|
||||||
|
void free_upcall_info(struct clnt_upcall_info *info);
|
||||||
|
+void gssd_free_client(struct clnt_info *clp);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _RPC_GSSD_H_ */
|
||||||
|
diff -up nfs-utils-2.3.3/utils/gssd/gssd_proc.c.orig nfs-utils-2.3.3/utils/gssd/gssd_proc.c
|
||||||
|
--- nfs-utils-2.3.3/utils/gssd/gssd_proc.c.orig 2021-07-19 09:39:04.269895430 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/gssd/gssd_proc.c 2021-07-19 09:40:13.944751267 -0400
|
||||||
|
@@ -80,6 +80,8 @@
|
||||||
|
#include "nfslib.h"
|
||||||
|
#include "gss_names.h"
|
||||||
|
|
||||||
|
+extern pthread_mutex_t clp_lock;
|
||||||
|
+
|
||||||
|
/* Encryption types supported by the kernel rpcsec_gss code */
|
||||||
|
int num_krb5_enctypes = 0;
|
||||||
|
krb5_enctype *krb5_enctypes = NULL;
|
||||||
|
@@ -719,22 +721,133 @@ out_return_error:
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
-void
|
||||||
|
-handle_krb5_upcall(struct clnt_upcall_info *info)
|
||||||
|
-{
|
||||||
|
- struct clnt_info *clp = info->clp;
|
||||||
|
+static struct clnt_upcall_info *
|
||||||
|
+alloc_upcall_info(struct clnt_info *clp, uid_t uid, int fd, char *srchost,
|
||||||
|
+ char *target, char *service)
|
||||||
|
+{
|
||||||
|
+ struct clnt_upcall_info *info;
|
||||||
|
+
|
||||||
|
+ info = malloc(sizeof(struct clnt_upcall_info));
|
||||||
|
+ if (info == NULL)
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ memset(info, 0, sizeof(*info));
|
||||||
|
+ pthread_mutex_lock(&clp_lock);
|
||||||
|
+ clp->refcount++;
|
||||||
|
+ pthread_mutex_unlock(&clp_lock);
|
||||||
|
+ info->clp = clp;
|
||||||
|
+ info->uid = uid;
|
||||||
|
+ info->fd = fd;
|
||||||
|
+ if (srchost) {
|
||||||
|
+ info->srchost = strdup(srchost);
|
||||||
|
+ if (info->srchost == NULL)
|
||||||
|
+ goto out_info;
|
||||||
|
+ }
|
||||||
|
+ if (target) {
|
||||||
|
+ info->target = strdup(target);
|
||||||
|
+ if (info->target == NULL)
|
||||||
|
+ goto out_srchost;
|
||||||
|
+ }
|
||||||
|
+ if (service) {
|
||||||
|
+ info->service = strdup(service);
|
||||||
|
+ if (info->service == NULL)
|
||||||
|
+ goto out_target;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+out:
|
||||||
|
+ return info;
|
||||||
|
|
||||||
|
- printerr(2, "\n%s: uid %d (%s)\n", __func__, info->uid, clp->relpath);
|
||||||
|
+out_target:
|
||||||
|
+ if (info->target)
|
||||||
|
+ free(info->target);
|
||||||
|
+out_srchost:
|
||||||
|
+ if (info->srchost)
|
||||||
|
+ free(info->srchost);
|
||||||
|
+out_info:
|
||||||
|
+ free(info);
|
||||||
|
+ info = NULL;
|
||||||
|
+ goto out;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void free_upcall_info(struct clnt_upcall_info *info)
|
||||||
|
+{
|
||||||
|
+ gssd_free_client(info->clp);
|
||||||
|
+ if (info->service)
|
||||||
|
+ free(info->service);
|
||||||
|
+ if (info->target)
|
||||||
|
+ free(info->target);
|
||||||
|
+ if (info->srchost)
|
||||||
|
+ free(info->srchost);
|
||||||
|
+ free(info);
|
||||||
|
+}
|
||||||
|
|
||||||
|
- process_krb5_upcall(clp, info->uid, clp->krb5_fd, NULL, NULL, NULL);
|
||||||
|
+static void
|
||||||
|
+gssd_work_thread_fn(struct clnt_upcall_info *info)
|
||||||
|
+{
|
||||||
|
+ process_krb5_upcall(info->clp, info->uid, info->fd, info->srchost, info->target, info->service);
|
||||||
|
free_upcall_info(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+start_upcall_thread(void (*func)(struct clnt_upcall_info *), void *info)
|
||||||
|
+{
|
||||||
|
+ pthread_attr_t attr;
|
||||||
|
+ pthread_t th;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = pthread_attr_init(&attr);
|
||||||
|
+ if (ret != 0) {
|
||||||
|
+ printerr(0, "ERROR: failed to init pthread attr: ret %d: %s\n",
|
||||||
|
+ ret, strerror(errno));
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+ ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||||
|
+ if (ret != 0) {
|
||||||
|
+ printerr(0, "ERROR: failed to create pthread attr: ret %d: "
|
||||||
|
+ "%s\n", ret, strerror(errno));
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = pthread_create(&th, &attr, (void *)func, (void *)info);
|
||||||
|
+ if (ret != 0)
|
||||||
|
+ printerr(0, "ERROR: pthread_create failed: ret %d: %s\n",
|
||||||
|
+ ret, strerror(errno));
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
-handle_gssd_upcall(struct clnt_upcall_info *info)
|
||||||
|
+handle_krb5_upcall(struct clnt_info *clp)
|
||||||
|
{
|
||||||
|
- struct clnt_info *clp = info->clp;
|
||||||
|
uid_t uid;
|
||||||
|
+ struct clnt_upcall_info *info;
|
||||||
|
+ int err;
|
||||||
|
+
|
||||||
|
+ if (read(clp->krb5_fd, &uid, sizeof(uid)) < (ssize_t)sizeof(uid)) {
|
||||||
|
+ printerr(0, "WARNING: failed reading uid from krb5 "
|
||||||
|
+ "upcall pipe: %s\n", strerror(errno));
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ printerr(2, "\n%s: uid %d (%s)\n", __func__, uid, clp->relpath);
|
||||||
|
+
|
||||||
|
+ info = alloc_upcall_info(clp, uid, clp->krb5_fd, NULL, NULL, NULL);
|
||||||
|
+ if (info == NULL) {
|
||||||
|
+ printerr(0, "%s: failed to allocate clnt_upcall_info\n", __func__);
|
||||||
|
+ do_error_downcall(clp->krb5_fd, uid, -EACCES);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ err = start_upcall_thread(gssd_work_thread_fn, info);
|
||||||
|
+ if (err != 0) {
|
||||||
|
+ do_error_downcall(clp->krb5_fd, uid, -EACCES);
|
||||||
|
+ free_upcall_info(info);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+handle_gssd_upcall(struct clnt_info *clp)
|
||||||
|
+{
|
||||||
|
+ uid_t uid;
|
||||||
|
+ char lbuf[RPC_CHAN_BUF_SIZE];
|
||||||
|
+ int lbuflen = 0;
|
||||||
|
char *p;
|
||||||
|
char *mech = NULL;
|
||||||
|
char *uidstr = NULL;
|
||||||
|
@@ -742,20 +855,22 @@ handle_gssd_upcall(struct clnt_upcall_in
|
||||||
|
char *service = NULL;
|
||||||
|
char *srchost = NULL;
|
||||||
|
char *enctypes = NULL;
|
||||||
|
- char *upcall_str;
|
||||||
|
- char *pbuf = info->lbuf;
|
||||||
|
pthread_t tid = pthread_self();
|
||||||
|
+ struct clnt_upcall_info *info;
|
||||||
|
+ int err;
|
||||||
|
|
||||||
|
- printerr(2, "\n%s(0x%x): '%s' (%s)\n", __func__, tid,
|
||||||
|
- info->lbuf, clp->relpath);
|
||||||
|
-
|
||||||
|
- upcall_str = strdup(info->lbuf);
|
||||||
|
- if (upcall_str == NULL) {
|
||||||
|
- printerr(0, "ERROR: malloc failure\n");
|
||||||
|
- goto out_nomem;
|
||||||
|
+ lbuflen = read(clp->gssd_fd, lbuf, sizeof(lbuf));
|
||||||
|
+ if (lbuflen <= 0 || lbuf[lbuflen-1] != '\n') {
|
||||||
|
+ printerr(0, "WARNING: handle_gssd_upcall: "
|
||||||
|
+ "failed reading request\n");
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
+ lbuf[lbuflen-1] = 0;
|
||||||
|
+
|
||||||
|
+ printerr(2, "\n%s(0x%x): '%s' (%s)\n", __func__, tid,
|
||||||
|
+ lbuf, clp->relpath);
|
||||||
|
|
||||||
|
- while ((p = strsep(&pbuf, " "))) {
|
||||||
|
+ for (p = strtok(lbuf, " "); p; p = strtok(NULL, " ")) {
|
||||||
|
if (!strncmp(p, "mech=", strlen("mech=")))
|
||||||
|
mech = p + strlen("mech=");
|
||||||
|
else if (!strncmp(p, "uid=", strlen("uid=")))
|
||||||
|
@@ -773,8 +888,8 @@ handle_gssd_upcall(struct clnt_upcall_in
|
||||||
|
if (!mech || strlen(mech) < 1) {
|
||||||
|
printerr(0, "WARNING: handle_gssd_upcall: "
|
||||||
|
"failed to find gss mechanism name "
|
||||||
|
- "in upcall string '%s'\n", upcall_str);
|
||||||
|
- goto out;
|
||||||
|
+ "in upcall string '%s'\n", lbuf);
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uidstr) {
|
||||||
|
@@ -786,21 +901,21 @@ handle_gssd_upcall(struct clnt_upcall_in
|
||||||
|
if (!uidstr) {
|
||||||
|
printerr(0, "WARNING: handle_gssd_upcall: "
|
||||||
|
"failed to find uid "
|
||||||
|
- "in upcall string '%s'\n", upcall_str);
|
||||||
|
- goto out;
|
||||||
|
+ "in upcall string '%s'\n", lbuf);
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enctypes && parse_enctypes(enctypes) != 0) {
|
||||||
|
printerr(0, "WARNING: handle_gssd_upcall: "
|
||||||
|
"parsing encryption types failed: errno %d\n", errno);
|
||||||
|
- goto out;
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target && strlen(target) < 1) {
|
||||||
|
printerr(0, "WARNING: handle_gssd_upcall: "
|
||||||
|
"failed to parse target name "
|
||||||
|
- "in upcall string '%s'\n", upcall_str);
|
||||||
|
- goto out;
|
||||||
|
+ "in upcall string '%s'\n", lbuf);
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -814,21 +929,26 @@ handle_gssd_upcall(struct clnt_upcall_in
|
||||||
|
if (service && strlen(service) < 1) {
|
||||||
|
printerr(0, "WARNING: handle_gssd_upcall: "
|
||||||
|
"failed to parse service type "
|
||||||
|
- "in upcall string '%s'\n", upcall_str);
|
||||||
|
- goto out;
|
||||||
|
+ "in upcall string '%s'\n", lbuf);
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (strcmp(mech, "krb5") == 0 && clp->servername)
|
||||||
|
- process_krb5_upcall(clp, uid, clp->gssd_fd, srchost, target, service);
|
||||||
|
- else {
|
||||||
|
+ if (strcmp(mech, "krb5") == 0 && clp->servername) {
|
||||||
|
+ info = alloc_upcall_info(clp, uid, clp->gssd_fd, srchost, target, service);
|
||||||
|
+ if (info == NULL) {
|
||||||
|
+ printerr(0, "%s: failed to allocate clnt_upcall_info\n", __func__);
|
||||||
|
+ do_error_downcall(clp->gssd_fd, uid, -EACCES);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ err = start_upcall_thread(gssd_work_thread_fn, info);
|
||||||
|
+ if (err != 0) {
|
||||||
|
+ do_error_downcall(clp->gssd_fd, uid, -EACCES);
|
||||||
|
+ free_upcall_info(info);
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
if (clp->servername)
|
||||||
|
printerr(0, "WARNING: handle_gssd_upcall: "
|
||||||
|
"received unknown gss mech '%s'\n", mech);
|
||||||
|
do_error_downcall(clp->gssd_fd, uid, -EACCES);
|
||||||
|
}
|
||||||
|
-out:
|
||||||
|
- free(upcall_str);
|
||||||
|
-out_nomem:
|
||||||
|
- free_upcall_info(info);
|
||||||
|
- return;
|
||||||
|
}
|
141
SOURCES/nfs-utils-2.3.3-gssd-k5identity.patch
Normal file
141
SOURCES/nfs-utils-2.3.3-gssd-k5identity.patch
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
diff -up nfs-utils-2.3.3/nfs.conf.orig nfs-utils-2.3.3/nfs.conf
|
||||||
|
--- nfs-utils-2.3.3/nfs.conf.orig 2021-04-17 10:49:23.660184527 -0400
|
||||||
|
+++ nfs-utils-2.3.3/nfs.conf 2021-04-17 11:14:41.482108562 -0400
|
||||||
|
@@ -21,6 +21,7 @@ use-gss-proxy=1
|
||||||
|
# keytab-file=/etc/krb5.keytab
|
||||||
|
# cred-cache-directory=
|
||||||
|
# preferred-realm=
|
||||||
|
+# set-home=1
|
||||||
|
#
|
||||||
|
[lockd]
|
||||||
|
# port=0
|
||||||
|
diff -up nfs-utils-2.3.3/systemd/nfs.conf.man.orig nfs-utils-2.3.3/systemd/nfs.conf.man
|
||||||
|
--- nfs-utils-2.3.3/systemd/nfs.conf.man.orig 2021-04-17 10:49:23.696185472 -0400
|
||||||
|
+++ nfs-utils-2.3.3/systemd/nfs.conf.man 2021-04-17 11:14:41.483108588 -0400
|
||||||
|
@@ -222,7 +222,8 @@ Recognized values:
|
||||||
|
.BR rpc-timeout ,
|
||||||
|
.BR keytab-file ,
|
||||||
|
.BR cred-cache-directory ,
|
||||||
|
-.BR preferred-realm .
|
||||||
|
+.BR preferred-realm ,
|
||||||
|
+.BR set-home .
|
||||||
|
|
||||||
|
See
|
||||||
|
.BR rpc.gssd (8)
|
||||||
|
diff -up nfs-utils-2.3.3/utils/gssd/gssd.c.orig nfs-utils-2.3.3/utils/gssd/gssd.c
|
||||||
|
--- nfs-utils-2.3.3/utils/gssd/gssd.c.orig 2021-04-17 10:49:23.684185157 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/gssd/gssd.c 2021-04-17 11:14:41.483108588 -0400
|
||||||
|
@@ -87,6 +87,8 @@ unsigned int context_timeout = 0;
|
||||||
|
unsigned int rpc_timeout = 5;
|
||||||
|
char *preferred_realm = NULL;
|
||||||
|
char *ccachedir = NULL;
|
||||||
|
+/* set $HOME to "/" by default */
|
||||||
|
+static bool set_home = true;
|
||||||
|
/* Avoid DNS reverse lookups on server names */
|
||||||
|
static bool avoid_dns = true;
|
||||||
|
static bool use_gssproxy = false;
|
||||||
|
@@ -885,7 +887,7 @@ sig_die(int signal)
|
||||||
|
static void
|
||||||
|
usage(char *progname)
|
||||||
|
{
|
||||||
|
- fprintf(stderr, "usage: %s [-f] [-l] [-M] [-n] [-v] [-r] [-p pipefsdir] [-k keytab] [-d ccachedir] [-t timeout] [-R preferred realm] [-D]\n",
|
||||||
|
+ fprintf(stderr, "usage: %s [-f] [-l] [-M] [-n] [-v] [-r] [-p pipefsdir] [-k keytab] [-d ccachedir] [-t timeout] [-R preferred realm] [-D] [-H]\n",
|
||||||
|
progname);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
@@ -926,6 +928,7 @@ read_gss_conf(void)
|
||||||
|
preferred_realm = s;
|
||||||
|
|
||||||
|
use_gssproxy = conf_get_bool("gssd", "use-gss-proxy", use_gssproxy);
|
||||||
|
+ set_home = conf_get_bool("gssd", "set-home", set_home);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
@@ -946,7 +949,7 @@ main(int argc, char *argv[])
|
||||||
|
verbosity = conf_get_num("gssd", "verbosity", verbosity);
|
||||||
|
rpc_verbosity = conf_get_num("gssd", "rpc-verbosity", rpc_verbosity);
|
||||||
|
|
||||||
|
- while ((opt = getopt(argc, argv, "DfvrlmnMp:k:d:t:T:R:")) != -1) {
|
||||||
|
+ while ((opt = getopt(argc, argv, "HDfvrlmnMp:k:d:t:T:R:")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'f':
|
||||||
|
fg = 1;
|
||||||
|
@@ -994,6 +997,9 @@ main(int argc, char *argv[])
|
||||||
|
case 'D':
|
||||||
|
avoid_dns = false;
|
||||||
|
break;
|
||||||
|
+ case 'H':
|
||||||
|
+ set_home = false;
|
||||||
|
+ break;
|
||||||
|
default:
|
||||||
|
usage(argv[0]);
|
||||||
|
break;
|
||||||
|
@@ -1003,13 +1009,19 @@ main(int argc, char *argv[])
|
||||||
|
/*
|
||||||
|
* Some krb5 routines try to scrape info out of files in the user's
|
||||||
|
* home directory. This can easily deadlock when that homedir is on a
|
||||||
|
- * kerberized NFS mount. By setting $HOME unconditionally to "/", we
|
||||||
|
- * prevent this behavior in routines that use $HOME in preference to
|
||||||
|
- * the results of getpw*.
|
||||||
|
+ * kerberized NFS mount. By setting $HOME to "/" by default, we prevent
|
||||||
|
+ * this behavior in routines that use $HOME in preference to the results
|
||||||
|
+ * of getpw*.
|
||||||
|
+ *
|
||||||
|
+ * Some users do not use Kerberized home dirs and need $HOME to remain
|
||||||
|
+ * unchanged. Those users can leave $HOME unchanged by setting set_home
|
||||||
|
+ * to false.
|
||||||
|
*/
|
||||||
|
- if (setenv("HOME", "/", 1)) {
|
||||||
|
- printerr(0, "gssd: Unable to set $HOME: %s\n", strerror(errno));
|
||||||
|
- exit(1);
|
||||||
|
+ if (set_home) {
|
||||||
|
+ if (setenv("HOME", "/", 1)) {
|
||||||
|
+ printerr(0, "gssd: Unable to set $HOME: %s\n", strerror(errno));
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use_gssproxy) {
|
||||||
|
diff -up nfs-utils-2.3.3/utils/gssd/gssd.man.orig nfs-utils-2.3.3/utils/gssd/gssd.man
|
||||||
|
--- nfs-utils-2.3.3/utils/gssd/gssd.man.orig 2021-04-17 10:49:23.650184264 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/gssd/gssd.man 2021-04-17 11:14:41.484108615 -0400
|
||||||
|
@@ -8,7 +8,7 @@
|
||||||
|
rpc.gssd \- RPCSEC_GSS daemon
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B rpc.gssd
|
||||||
|
-.RB [ \-DfMnlvr ]
|
||||||
|
+.RB [ \-DfMnlvrH ]
|
||||||
|
.RB [ \-k
|
||||||
|
.IR keytab ]
|
||||||
|
.RB [ \-p
|
||||||
|
@@ -297,6 +297,16 @@ The default timeout is set to 5 seconds.
|
||||||
|
If you get messages like "WARNING: can't create tcp rpc_clnt to server
|
||||||
|
%servername% for user with uid %uid%: RPC: Remote system error -
|
||||||
|
Connection timed out", you should consider an increase of this timeout.
|
||||||
|
+.TP
|
||||||
|
+.B -H
|
||||||
|
+Avoids setting $HOME to "/". This allows rpc.gssd to read per user k5identity
|
||||||
|
+files versus trying to read /.k5identity for each user.
|
||||||
|
+
|
||||||
|
+If
|
||||||
|
+.B \-H
|
||||||
|
+is not set, rpc.gssd will use the first match found in
|
||||||
|
+/var/kerberos/krb5/user/$EUID/client.keytab and will not use a principal based on
|
||||||
|
+host and/or service parameters listed in $HOME/.k5identity.
|
||||||
|
.SH CONFIGURATION FILE
|
||||||
|
Many of the options that can be set on the command line can also be
|
||||||
|
controlled through values set in the
|
||||||
|
@@ -354,6 +364,13 @@ Equivalent to
|
||||||
|
.B preferred-realm
|
||||||
|
Equivalent to
|
||||||
|
.BR -R .
|
||||||
|
+.TP
|
||||||
|
+.B set-home
|
||||||
|
+Setting to
|
||||||
|
+.B false
|
||||||
|
+is equivalent to providing the
|
||||||
|
+.B -H
|
||||||
|
+flag.
|
||||||
|
.P
|
||||||
|
In addtion, the following value is recognized from the
|
||||||
|
.B [general]
|
@ -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
|
||||||
|
|
17
SOURCES/nfs-utils-2.3.3-gssd-man-tflag.patch
Normal file
17
SOURCES/nfs-utils-2.3.3-gssd-man-tflag.patch
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
diff -up nfs-utils-2.3.3/utils/gssd/gssd.man.orig nfs-utils-2.3.3/utils/gssd/gssd.man
|
||||||
|
--- nfs-utils-2.3.3/utils/gssd/gssd.man.orig 2021-04-17 11:21:18.326543446 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/gssd/gssd.man 2021-04-17 12:35:59.867574517 -0400
|
||||||
|
@@ -347,11 +347,11 @@ Equivalent to
|
||||||
|
.TP
|
||||||
|
.B context-timeout
|
||||||
|
Equivalent to
|
||||||
|
-.BR -T .
|
||||||
|
+.BR -t .
|
||||||
|
.TP
|
||||||
|
.B rpc-timeout
|
||||||
|
Equivalent to
|
||||||
|
-.BR -t .
|
||||||
|
+.BR -T .
|
||||||
|
.TP
|
||||||
|
.B keytab-file
|
||||||
|
Equivalent to
|
1009
SOURCES/nfs-utils-2.3.3-gssd-multithread-updates.patch
Normal file
1009
SOURCES/nfs-utils-2.3.3-gssd-multithread-updates.patch
Normal file
File diff suppressed because it is too large
Load Diff
43
SOURCES/nfs-utils-2.3.3-gssd-mutex-refcnt.patch
Normal file
43
SOURCES/nfs-utils-2.3.3-gssd-mutex-refcnt.patch
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
diff -up nfs-utils-2.3.3/utils/gssd/krb5_util.c.orig nfs-utils-2.3.3/utils/gssd/krb5_util.c
|
||||||
|
--- nfs-utils-2.3.3/utils/gssd/krb5_util.c.orig 2021-07-22 15:27:27.728680553 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/gssd/krb5_util.c 2021-07-22 15:30:08.916979585 -0400
|
||||||
|
@@ -165,18 +165,28 @@ static int gssd_get_single_krb5_cred(krb
|
||||||
|
static int query_krb5_ccache(const char* cred_cache, char **ret_princname,
|
||||||
|
char **ret_realm);
|
||||||
|
|
||||||
|
-static void release_ple(krb5_context context, struct gssd_k5_kt_princ *ple)
|
||||||
|
+static void release_ple_locked(krb5_context context,
|
||||||
|
+ struct gssd_k5_kt_princ *ple)
|
||||||
|
{
|
||||||
|
if (--ple->refcount)
|
||||||
|
return;
|
||||||
|
|
||||||
|
- printerr(3, "freeing cached principal (ccname=%s, realm=%s)\n", ple->ccname, ple->realm);
|
||||||
|
+ printerr(3, "freeing cached principal (ccname=%s, realm=%s)\n",
|
||||||
|
+ ple->ccname, ple->realm);
|
||||||
|
krb5_free_principal(context, ple->princ);
|
||||||
|
free(ple->ccname);
|
||||||
|
free(ple->realm);
|
||||||
|
free(ple);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void release_ple(krb5_context context, struct gssd_k5_kt_princ *ple)
|
||||||
|
+{
|
||||||
|
+ pthread_mutex_lock(&ple_lock);
|
||||||
|
+ release_ple_locked(context, ple);
|
||||||
|
+ pthread_mutex_unlock(&ple_lock);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Called from the scandir function to weed out potential krb5
|
||||||
|
* credentials cache files
|
||||||
|
@@ -1396,7 +1406,7 @@ gssd_destroy_krb5_principals(int destroy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- release_ple(context, ple);
|
||||||
|
+ release_ple_locked(context, ple);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&ple_lock);
|
||||||
|
krb5_free_context(context);
|
14
SOURCES/nfs-utils-2.3.3-gssd-printerr.patch
Normal file
14
SOURCES/nfs-utils-2.3.3-gssd-printerr.patch
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
diff -up nfs-utils-2.3.3/utils/gssd/krb5_util.c.orig nfs-utils-2.3.3/utils/gssd/krb5_util.c
|
||||||
|
--- nfs-utils-2.3.3/utils/gssd/krb5_util.c.orig 2021-11-04 10:13:07.788142847 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/gssd/krb5_util.c 2021-11-04 10:14:10.829841090 -0400
|
||||||
|
@@ -647,8 +647,8 @@ get_full_hostname(const char *inhost, ch
|
||||||
|
*c = tolower(*c);
|
||||||
|
|
||||||
|
if (get_verbosity() && strcmp(inhost, outhost))
|
||||||
|
- printerr(1, "%s(0x%0lx): inhost '%s' different than outhost'%s'\n",
|
||||||
|
- inhost, outhost);
|
||||||
|
+ printerr(1, "%s(0x%0lx): inhost '%s' different than outhost '%s'\n",
|
||||||
|
+ __func__, tid, inhost, outhost);
|
||||||
|
|
||||||
|
retval = 0;
|
||||||
|
out:
|
625
SOURCES/nfs-utils-2.3.3-gssd-timeout-thread.patch
Normal file
625
SOURCES/nfs-utils-2.3.3-gssd-timeout-thread.patch
Normal file
@ -0,0 +1,625 @@
|
|||||||
|
diff -up nfs-utils-2.3.3/nfs.conf.orig nfs-utils-2.3.3/nfs.conf
|
||||||
|
--- nfs-utils-2.3.3/nfs.conf.orig 2021-07-19 09:45:40.441448059 -0400
|
||||||
|
+++ nfs-utils-2.3.3/nfs.conf 2021-07-19 12:08:55.314182838 -0400
|
||||||
|
@@ -22,6 +22,8 @@ use-gss-proxy=1
|
||||||
|
# cred-cache-directory=
|
||||||
|
# preferred-realm=
|
||||||
|
# set-home=1
|
||||||
|
+# upcall-timeout=30
|
||||||
|
+# cancel-timed-out-upcalls=0
|
||||||
|
#
|
||||||
|
[lockd]
|
||||||
|
# port=0
|
||||||
|
diff -up nfs-utils-2.3.3/utils/gssd/gssd.c.orig nfs-utils-2.3.3/utils/gssd/gssd.c
|
||||||
|
--- nfs-utils-2.3.3/utils/gssd/gssd.c.orig 2021-07-19 09:45:40.448448246 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/gssd/gssd.c 2021-07-19 12:08:55.315182865 -0400
|
||||||
|
@@ -96,8 +96,29 @@ pthread_mutex_t clp_lock = PTHREAD_MUTEX
|
||||||
|
static bool signal_received = false;
|
||||||
|
static struct event_base *evbase = NULL;
|
||||||
|
|
||||||
|
+int upcall_timeout = DEF_UPCALL_TIMEOUT;
|
||||||
|
+static bool cancel_timed_out_upcalls = false;
|
||||||
|
+
|
||||||
|
TAILQ_HEAD(topdir_list_head, topdir) topdir_list;
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * active_thread_list:
|
||||||
|
+ *
|
||||||
|
+ * used to track upcalls for timeout purposes.
|
||||||
|
+ *
|
||||||
|
+ * protected by the active_thread_list_lock mutex.
|
||||||
|
+ *
|
||||||
|
+ * upcall_thread_info structures are added to the tail of the list
|
||||||
|
+ * by start_upcall_thread(), so entries closer to the head of the list
|
||||||
|
+ * will be closer to hitting the upcall timeout.
|
||||||
|
+ *
|
||||||
|
+ * upcall_thread_info structures are removed from the list upon a
|
||||||
|
+ * sucessful join of the upcall thread by the watchdog thread (via
|
||||||
|
+ * scan_active_thread_list().
|
||||||
|
+ */
|
||||||
|
+TAILQ_HEAD(active_thread_list_head, upcall_thread_info) active_thread_list;
|
||||||
|
+pthread_mutex_t active_thread_list_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
+
|
||||||
|
struct topdir {
|
||||||
|
TAILQ_ENTRY(topdir) list;
|
||||||
|
TAILQ_HEAD(clnt_list_head, clnt_info) clnt_list;
|
||||||
|
@@ -436,6 +457,138 @@ gssd_clnt_krb5_cb(int UNUSED(fd), short
|
||||||
|
handle_krb5_upcall(clp);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * scan_active_thread_list:
|
||||||
|
+ *
|
||||||
|
+ * Walks the active_thread_list, trying to join as many upcall threads as
|
||||||
|
+ * possible. For threads that have terminated, the corresponding
|
||||||
|
+ * upcall_thread_info will be removed from the list and freed. Threads that
|
||||||
|
+ * are still busy and have exceeded the upcall_timeout will cause an error to
|
||||||
|
+ * be logged and may be canceled (depending on the value of
|
||||||
|
+ * cancel_timed_out_upcalls).
|
||||||
|
+ *
|
||||||
|
+ * Returns the number of seconds that the watchdog thread should wait before
|
||||||
|
+ * calling scan_active_thread_list() again.
|
||||||
|
+ */
|
||||||
|
+static int
|
||||||
|
+scan_active_thread_list(void)
|
||||||
|
+{
|
||||||
|
+ struct upcall_thread_info *info;
|
||||||
|
+ struct timespec now;
|
||||||
|
+ unsigned int sleeptime;
|
||||||
|
+ bool sleeptime_set = false;
|
||||||
|
+ int err;
|
||||||
|
+ void *tret, *saveprev;
|
||||||
|
+
|
||||||
|
+ sleeptime = upcall_timeout;
|
||||||
|
+ pthread_mutex_lock(&active_thread_list_lock);
|
||||||
|
+ clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
+ TAILQ_FOREACH(info, &active_thread_list, list) {
|
||||||
|
+ err = pthread_tryjoin_np(info->tid, &tret);
|
||||||
|
+ switch (err) {
|
||||||
|
+ case 0:
|
||||||
|
+ /*
|
||||||
|
+ * The upcall thread has either completed successfully, or
|
||||||
|
+ * has been canceled _and_ has acted on the cancellation request
|
||||||
|
+ * (i.e. has hit a cancellation point). We can now remove the
|
||||||
|
+ * upcall_thread_info from the list and free it.
|
||||||
|
+ */
|
||||||
|
+ if (tret == PTHREAD_CANCELED)
|
||||||
|
+ printerr(3, "watchdog: thread id 0x%lx cancelled successfully\n",
|
||||||
|
+ info->tid);
|
||||||
|
+ saveprev = info->list.tqe_prev;
|
||||||
|
+ TAILQ_REMOVE(&active_thread_list, info, list);
|
||||||
|
+ free(info);
|
||||||
|
+ info = saveprev;
|
||||||
|
+ break;
|
||||||
|
+ case EBUSY:
|
||||||
|
+ /*
|
||||||
|
+ * The upcall thread is still running. If the timeout has expired
|
||||||
|
+ * then we either cancel the thread, log an error, and do an error
|
||||||
|
+ * downcall to the kernel (cancel_timed_out_upcalls=true) or simply
|
||||||
|
+ * log an error (cancel_timed_out_upcalls=false). In either case,
|
||||||
|
+ * the error is logged only once.
|
||||||
|
+ */
|
||||||
|
+ if (now.tv_sec >= info->timeout.tv_sec) {
|
||||||
|
+ if (cancel_timed_out_upcalls && !(info->flags & UPCALL_THREAD_CANCELED)) {
|
||||||
|
+ printerr(0, "watchdog: thread id 0x%lx timed out\n",
|
||||||
|
+ info->tid);
|
||||||
|
+ pthread_cancel(info->tid);
|
||||||
|
+ info->flags |= (UPCALL_THREAD_CANCELED|UPCALL_THREAD_WARNED);
|
||||||
|
+ do_error_downcall(info->fd, info->uid, -ETIMEDOUT);
|
||||||
|
+ } else {
|
||||||
|
+ if (!(info->flags & UPCALL_THREAD_WARNED)) {
|
||||||
|
+ printerr(0, "watchdog: thread id 0x%lx running for %ld seconds\n",
|
||||||
|
+ info->tid,
|
||||||
|
+ now.tv_sec - info->timeout.tv_sec + upcall_timeout);
|
||||||
|
+ info->flags |= UPCALL_THREAD_WARNED;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ } else if (!sleeptime_set) {
|
||||||
|
+ /*
|
||||||
|
+ * The upcall thread is still running, but the timeout has not yet
|
||||||
|
+ * expired. Calculate the time remaining until the timeout will
|
||||||
|
+ * expire. This is the amount of time the watchdog thread will
|
||||||
|
+ * wait before running again. We only need to do this for the busy
|
||||||
|
+ * thread closest to the head of the list - entries appearing later
|
||||||
|
+ * in the list will time out later.
|
||||||
|
+ */
|
||||||
|
+ sleeptime = info->timeout.tv_sec - now.tv_sec;
|
||||||
|
+ sleeptime_set = true;
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ /* EDEADLK, EINVAL, and ESRCH... none of which should happen! */
|
||||||
|
+ printerr(0, "watchdog: attempt to join thread id 0x%lx returned %d (%s)!\n",
|
||||||
|
+ info->tid, err, strerror(err));
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ pthread_mutex_unlock(&active_thread_list_lock);
|
||||||
|
+
|
||||||
|
+ return sleeptime;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void *
|
||||||
|
+watchdog_thread_fn(void *UNUSED(arg))
|
||||||
|
+{
|
||||||
|
+ unsigned int sleeptime;
|
||||||
|
+
|
||||||
|
+ for (;;) {
|
||||||
|
+ sleeptime = scan_active_thread_list();
|
||||||
|
+ printerr(4, "watchdog: sleeping %u secs\n", sleeptime);
|
||||||
|
+ sleep(sleeptime);
|
||||||
|
+ }
|
||||||
|
+ return (void *)0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+start_watchdog_thread(void)
|
||||||
|
+{
|
||||||
|
+ pthread_attr_t attr;
|
||||||
|
+ pthread_t th;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = pthread_attr_init(&attr);
|
||||||
|
+ if (ret != 0) {
|
||||||
|
+ printerr(0, "ERROR: failed to init pthread attr: ret %d: %s\n",
|
||||||
|
+ ret, strerror(errno));
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+ ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||||
|
+ if (ret != 0) {
|
||||||
|
+ printerr(0, "ERROR: failed to create pthread attr: ret %d: %s\n",
|
||||||
|
+ ret, strerror(errno));
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+ ret = pthread_create(&th, &attr, watchdog_thread_fn, NULL);
|
||||||
|
+ if (ret != 0) {
|
||||||
|
+ printerr(0, "ERROR: pthread_create failed: ret %d: %s\n",
|
||||||
|
+ ret, strerror(errno));
|
||||||
|
+ }
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static struct clnt_info *
|
||||||
|
gssd_get_clnt(struct topdir *tdi, const char *name)
|
||||||
|
{
|
||||||
|
@@ -810,7 +963,7 @@ sig_die(int signal)
|
||||||
|
static void
|
||||||
|
usage(char *progname)
|
||||||
|
{
|
||||||
|
- fprintf(stderr, "usage: %s [-f] [-l] [-M] [-n] [-v] [-r] [-p pipefsdir] [-k keytab] [-d ccachedir] [-t timeout] [-R preferred realm] [-D] [-H]\n",
|
||||||
|
+ fprintf(stderr, "usage: %s [-f] [-l] [-M] [-n] [-v] [-r] [-p pipefsdir] [-k keytab] [-d ccachedir] [-t timeout] [-R preferred realm] [-D] [-H] [-U upcall timeout] [-C]\n",
|
||||||
|
progname);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
@@ -831,6 +984,9 @@ read_gss_conf(void)
|
||||||
|
#endif
|
||||||
|
context_timeout = conf_get_num("gssd", "context-timeout", context_timeout);
|
||||||
|
rpc_timeout = conf_get_num("gssd", "rpc-timeout", rpc_timeout);
|
||||||
|
+ upcall_timeout = conf_get_num("gssd", "upcall-timeout", upcall_timeout);
|
||||||
|
+ cancel_timed_out_upcalls = conf_get_bool("gssd", "cancel-timed-out-upcalls",
|
||||||
|
+ cancel_timed_out_upcalls);
|
||||||
|
s = conf_get_str("gssd", "pipefs-directory");
|
||||||
|
if (!s)
|
||||||
|
s = conf_get_str("general", "pipefs-directory");
|
||||||
|
@@ -872,7 +1028,7 @@ main(int argc, char *argv[])
|
||||||
|
verbosity = conf_get_num("gssd", "verbosity", verbosity);
|
||||||
|
rpc_verbosity = conf_get_num("gssd", "rpc-verbosity", rpc_verbosity);
|
||||||
|
|
||||||
|
- while ((opt = getopt(argc, argv, "HDfvrlmnMp:k:d:t:T:R:")) != -1) {
|
||||||
|
+ while ((opt = getopt(argc, argv, "HDfvrlmnMp:k:d:t:T:R:U:C")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'f':
|
||||||
|
fg = 1;
|
||||||
|
@@ -923,6 +1079,12 @@ main(int argc, char *argv[])
|
||||||
|
case 'H':
|
||||||
|
set_home = false;
|
||||||
|
break;
|
||||||
|
+ case 'U':
|
||||||
|
+ upcall_timeout = atoi(optarg);
|
||||||
|
+ break;
|
||||||
|
+ case 'C':
|
||||||
|
+ cancel_timed_out_upcalls = true;
|
||||||
|
+ break;
|
||||||
|
default:
|
||||||
|
usage(argv[0]);
|
||||||
|
break;
|
||||||
|
@@ -995,6 +1157,11 @@ main(int argc, char *argv[])
|
||||||
|
else
|
||||||
|
progname = argv[0];
|
||||||
|
|
||||||
|
+ if (upcall_timeout > MAX_UPCALL_TIMEOUT)
|
||||||
|
+ upcall_timeout = MAX_UPCALL_TIMEOUT;
|
||||||
|
+ else if (upcall_timeout < MIN_UPCALL_TIMEOUT)
|
||||||
|
+ upcall_timeout = MIN_UPCALL_TIMEOUT;
|
||||||
|
+
|
||||||
|
initerr(progname, verbosity, fg);
|
||||||
|
#ifdef HAVE_LIBTIRPC_SET_DEBUG
|
||||||
|
/*
|
||||||
|
@@ -1045,6 +1212,14 @@ main(int argc, char *argv[])
|
||||||
|
gssd_inotify_cb, NULL);
|
||||||
|
event_add(inotify_ev, NULL);
|
||||||
|
|
||||||
|
+ TAILQ_INIT(&active_thread_list);
|
||||||
|
+
|
||||||
|
+ rc = start_watchdog_thread();
|
||||||
|
+ if (rc != 0) {
|
||||||
|
+ printerr(0, "ERROR: failed to start watchdog thread: %d\n", rc);
|
||||||
|
+ exit(EXIT_FAILURE);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
TAILQ_INIT(&topdir_list);
|
||||||
|
gssd_scan();
|
||||||
|
daemon_ready();
|
||||||
|
diff -up nfs-utils-2.3.3/utils/gssd/gssd.h.orig nfs-utils-2.3.3/utils/gssd/gssd.h
|
||||||
|
--- nfs-utils-2.3.3/utils/gssd/gssd.h.orig 2021-07-19 09:45:40.449448272 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/gssd/gssd.h 2021-07-19 12:08:55.315182865 -0400
|
||||||
|
@@ -50,6 +50,12 @@
|
||||||
|
#define GSSD_DEFAULT_KEYTAB_FILE "/etc/krb5.keytab"
|
||||||
|
#define GSSD_SERVICE_NAME "nfs"
|
||||||
|
#define RPC_CHAN_BUF_SIZE 32768
|
||||||
|
+
|
||||||
|
+/* timeouts are in seconds */
|
||||||
|
+#define MIN_UPCALL_TIMEOUT 5
|
||||||
|
+#define DEF_UPCALL_TIMEOUT 30
|
||||||
|
+#define MAX_UPCALL_TIMEOUT 600
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* The gss mechanisms that we can handle
|
||||||
|
*/
|
||||||
|
@@ -91,10 +97,22 @@ struct clnt_upcall_info {
|
||||||
|
char *service;
|
||||||
|
};
|
||||||
|
|
||||||
|
+struct upcall_thread_info {
|
||||||
|
+ TAILQ_ENTRY(upcall_thread_info) list;
|
||||||
|
+ pthread_t tid;
|
||||||
|
+ struct timespec timeout;
|
||||||
|
+ uid_t uid;
|
||||||
|
+ int fd;
|
||||||
|
+ unsigned short flags;
|
||||||
|
+#define UPCALL_THREAD_CANCELED 0x0001
|
||||||
|
+#define UPCALL_THREAD_WARNED 0x0002
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
void handle_krb5_upcall(struct clnt_info *clp);
|
||||||
|
void handle_gssd_upcall(struct clnt_info *clp);
|
||||||
|
void free_upcall_info(struct clnt_upcall_info *info);
|
||||||
|
void gssd_free_client(struct clnt_info *clp);
|
||||||
|
+int do_error_downcall(int k5_fd, uid_t uid, int err);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _RPC_GSSD_H_ */
|
||||||
|
diff -up nfs-utils-2.3.3/utils/gssd/gssd.man.orig nfs-utils-2.3.3/utils/gssd/gssd.man
|
||||||
|
--- nfs-utils-2.3.3/utils/gssd/gssd.man.orig 2021-07-19 09:45:40.443448112 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/gssd/gssd.man 2021-07-19 12:08:55.315182865 -0400
|
||||||
|
@@ -8,7 +8,7 @@
|
||||||
|
rpc.gssd \- RPCSEC_GSS daemon
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B rpc.gssd
|
||||||
|
-.RB [ \-DfMnlvrH ]
|
||||||
|
+.RB [ \-DfMnlvrHC ]
|
||||||
|
.RB [ \-k
|
||||||
|
.IR keytab ]
|
||||||
|
.RB [ \-p
|
||||||
|
@@ -17,6 +17,10 @@ rpc.gssd \- RPCSEC_GSS daemon
|
||||||
|
.IR ccachedir ]
|
||||||
|
.RB [ \-t
|
||||||
|
.IR timeout ]
|
||||||
|
+.RB [ \-T
|
||||||
|
+.IR timeout ]
|
||||||
|
+.RB [ \-U
|
||||||
|
+.IR timeout ]
|
||||||
|
.RB [ \-R
|
||||||
|
.IR realm ]
|
||||||
|
.SH INTRODUCTION
|
||||||
|
@@ -290,7 +294,7 @@ seconds, which allows changing Kerberos
|
||||||
|
The default is no explicit timeout, which means the kernel context will live
|
||||||
|
the lifetime of the Kerberos service ticket used in its creation.
|
||||||
|
.TP
|
||||||
|
-.B -T timeout
|
||||||
|
+.BI "-T " timeout
|
||||||
|
Timeout, in seconds, to create an RPC connection with a server while
|
||||||
|
establishing an authenticated gss context for a user.
|
||||||
|
The default timeout is set to 5 seconds.
|
||||||
|
@@ -298,6 +302,18 @@ If you get messages like "WARNING: can't
|
||||||
|
%servername% for user with uid %uid%: RPC: Remote system error -
|
||||||
|
Connection timed out", you should consider an increase of this timeout.
|
||||||
|
.TP
|
||||||
|
+.BI "-U " timeout
|
||||||
|
+Timeout, in seconds, for upcall threads. Threads executing longer than
|
||||||
|
+.I timeout
|
||||||
|
+seconds will cause an error message to be logged. The default
|
||||||
|
+.I timeout
|
||||||
|
+is 30 seconds. The minimum is 5 seconds. The maximum is 600 seconds.
|
||||||
|
+.TP
|
||||||
|
+.B -C
|
||||||
|
+In addition to logging an error message for threads that have timed out,
|
||||||
|
+the thread will be canceled and an error of -ETIMEDOUT will be reported
|
||||||
|
+to the kernel.
|
||||||
|
+.TP
|
||||||
|
.B -H
|
||||||
|
Avoids setting $HOME to "/". This allows rpc.gssd to read per user k5identity
|
||||||
|
files versus trying to read /.k5identity for each user.
|
||||||
|
@@ -365,6 +381,17 @@ Equivalent to
|
||||||
|
Equivalent to
|
||||||
|
.BR -R .
|
||||||
|
.TP
|
||||||
|
+.B upcall-timeout
|
||||||
|
+Equivalent to
|
||||||
|
+.BR -U .
|
||||||
|
+.TP
|
||||||
|
+.B cancel-timed-out-upcalls
|
||||||
|
+Setting to
|
||||||
|
+.B true
|
||||||
|
+is equivalent to providing the
|
||||||
|
+.B -C
|
||||||
|
+flag.
|
||||||
|
+.TP
|
||||||
|
.B set-home
|
||||||
|
Setting to
|
||||||
|
.B false
|
||||||
|
diff -up nfs-utils-2.3.3/utils/gssd/gssd_proc.c.orig nfs-utils-2.3.3/utils/gssd/gssd_proc.c
|
||||||
|
--- nfs-utils-2.3.3/utils/gssd/gssd_proc.c.orig 2021-07-19 09:45:40.449448272 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/gssd/gssd_proc.c 2021-07-19 12:08:55.316182891 -0400
|
||||||
|
@@ -81,11 +81,24 @@
|
||||||
|
#include "gss_names.h"
|
||||||
|
|
||||||
|
extern pthread_mutex_t clp_lock;
|
||||||
|
+extern pthread_mutex_t active_thread_list_lock;
|
||||||
|
+extern int upcall_timeout;
|
||||||
|
+extern TAILQ_HEAD(active_thread_list_head, upcall_thread_info) active_thread_list;
|
||||||
|
|
||||||
|
/* Encryption types supported by the kernel rpcsec_gss code */
|
||||||
|
int num_krb5_enctypes = 0;
|
||||||
|
krb5_enctype *krb5_enctypes = NULL;
|
||||||
|
|
||||||
|
+/* Args for the cleanup_handler() */
|
||||||
|
+struct cleanup_args {
|
||||||
|
+ OM_uint32 *min_stat;
|
||||||
|
+ gss_buffer_t acceptor;
|
||||||
|
+ gss_buffer_t token;
|
||||||
|
+ struct authgss_private_data *pd;
|
||||||
|
+ AUTH **auth;
|
||||||
|
+ CLIENT **rpc_clnt;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Parse the supported encryption type information
|
||||||
|
*/
|
||||||
|
@@ -184,7 +197,7 @@ out_err:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int
|
||||||
|
+int
|
||||||
|
do_error_downcall(int k5_fd, uid_t uid, int err)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
@@ -604,27 +617,66 @@ out:
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
+ * cleanup_handler:
|
||||||
|
+ *
|
||||||
|
+ * Free any resources allocated by process_krb5_upcall().
|
||||||
|
+ *
|
||||||
|
+ * Runs upon normal termination of process_krb5_upcall as well as if the
|
||||||
|
+ * thread is canceled.
|
||||||
|
+ */
|
||||||
|
+static void
|
||||||
|
+cleanup_handler(void *arg)
|
||||||
|
+{
|
||||||
|
+ struct cleanup_args *args = (struct cleanup_args *)arg;
|
||||||
|
+
|
||||||
|
+ gss_release_buffer(args->min_stat, args->acceptor);
|
||||||
|
+ if (args->token->value)
|
||||||
|
+ free(args->token->value);
|
||||||
|
+#ifdef HAVE_AUTHGSS_FREE_PRIVATE_DATA
|
||||||
|
+ if (args->pd->pd_ctx_hndl.length != 0 || args->pd->pd_ctx != 0)
|
||||||
|
+ authgss_free_private_data(args->pd);
|
||||||
|
+#endif
|
||||||
|
+ if (*args->auth)
|
||||||
|
+ AUTH_DESTROY(*args->auth);
|
||||||
|
+ if (*args->rpc_clnt)
|
||||||
|
+ clnt_destroy(*args->rpc_clnt);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * process_krb5_upcall:
|
||||||
|
+ *
|
||||||
|
* this code uses the userland rpcsec gss library to create a krb5
|
||||||
|
* context on behalf of the kernel
|
||||||
|
+ *
|
||||||
|
+ * This is the meat of the upcall thread. Note that cancelability is disabled
|
||||||
|
+ * and enabled at various points to ensure that any resources reserved by the
|
||||||
|
+ * lower level libraries are released safely.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
-process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *srchost,
|
||||||
|
- char *tgtname, char *service)
|
||||||
|
+process_krb5_upcall(struct clnt_upcall_info *info)
|
||||||
|
{
|
||||||
|
+ struct clnt_info *clp = info->clp;
|
||||||
|
+ uid_t uid = info->uid;
|
||||||
|
+ int fd = info->fd;
|
||||||
|
+ char *srchost = info->srchost;
|
||||||
|
+ char *tgtname = info->target;
|
||||||
|
+ char *service = info->service;
|
||||||
|
CLIENT *rpc_clnt = NULL;
|
||||||
|
AUTH *auth = NULL;
|
||||||
|
struct authgss_private_data pd;
|
||||||
|
gss_buffer_desc token;
|
||||||
|
- int err, downcall_err = -EACCES;
|
||||||
|
+ int err, downcall_err;
|
||||||
|
OM_uint32 maj_stat, min_stat, lifetime_rec;
|
||||||
|
gss_name_t gacceptor = GSS_C_NO_NAME;
|
||||||
|
gss_OID mech;
|
||||||
|
gss_buffer_desc acceptor = {0};
|
||||||
|
+ struct cleanup_args cleanup_args = {&min_stat, &acceptor, &token, &pd, &auth, &rpc_clnt};
|
||||||
|
|
||||||
|
token.length = 0;
|
||||||
|
token.value = NULL;
|
||||||
|
memset(&pd, 0, sizeof(struct authgss_private_data));
|
||||||
|
|
||||||
|
+ pthread_cleanup_push(cleanup_handler, &cleanup_args);
|
||||||
|
/*
|
||||||
|
* If "service" is specified, then the kernel is indicating that
|
||||||
|
* we must use machine credentials for this request. (Regardless
|
||||||
|
@@ -646,6 +698,8 @@ process_krb5_upcall(struct clnt_info *cl
|
||||||
|
* used for this case is not important.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
+ downcall_err = -EACCES;
|
||||||
|
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
||||||
|
if (uid != 0 || (uid == 0 && root_uses_machine_creds == 0 &&
|
||||||
|
service == NULL)) {
|
||||||
|
|
||||||
|
@@ -666,15 +720,21 @@ process_krb5_upcall(struct clnt_info *cl
|
||||||
|
goto out_return_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
||||||
|
+ pthread_testcancel();
|
||||||
|
|
||||||
|
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
||||||
|
if (!authgss_get_private_data(auth, &pd)) {
|
||||||
|
printerr(1, "WARNING: Failed to obtain authentication "
|
||||||
|
"data for user with uid %d for server %s\n",
|
||||||
|
uid, clp->servername);
|
||||||
|
goto out_return_error;
|
||||||
|
}
|
||||||
|
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
||||||
|
+ pthread_testcancel();
|
||||||
|
|
||||||
|
/* Grab the context lifetime and acceptor name out of the ctx. */
|
||||||
|
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
||||||
|
maj_stat = gss_inquire_context(&min_stat, pd.pd_ctx, NULL, &gacceptor,
|
||||||
|
&lifetime_rec, &mech, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
@@ -686,37 +746,35 @@ process_krb5_upcall(struct clnt_info *cl
|
||||||
|
get_hostbased_client_buffer(gacceptor, mech, &acceptor);
|
||||||
|
gss_release_name(&min_stat, &gacceptor);
|
||||||
|
}
|
||||||
|
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
||||||
|
+ pthread_testcancel();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The serialization can mean turning pd.pd_ctx into a lucid context. If
|
||||||
|
* that happens then the pd.pd_ctx will be unusable, so we must never
|
||||||
|
* try to use it after this point.
|
||||||
|
*/
|
||||||
|
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
||||||
|
if (serialize_context_for_kernel(&pd.pd_ctx, &token, &krb5oid, NULL)) {
|
||||||
|
printerr(1, "WARNING: Failed to serialize krb5 context for "
|
||||||
|
"user with uid %d for server %s\n",
|
||||||
|
uid, clp->servername);
|
||||||
|
goto out_return_error;
|
||||||
|
}
|
||||||
|
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
||||||
|
+ pthread_testcancel();
|
||||||
|
|
||||||
|
do_downcall(fd, uid, &pd, &token, lifetime_rec, &acceptor);
|
||||||
|
|
||||||
|
out:
|
||||||
|
- gss_release_buffer(&min_stat, &acceptor);
|
||||||
|
- if (token.value)
|
||||||
|
- free(token.value);
|
||||||
|
-#ifdef HAVE_AUTHGSS_FREE_PRIVATE_DATA
|
||||||
|
- if (pd.pd_ctx_hndl.length != 0 || pd.pd_ctx != 0)
|
||||||
|
- authgss_free_private_data(&pd);
|
||||||
|
-#endif
|
||||||
|
- if (auth)
|
||||||
|
- AUTH_DESTROY(auth);
|
||||||
|
- if (rpc_clnt)
|
||||||
|
- clnt_destroy(rpc_clnt);
|
||||||
|
+ pthread_cleanup_pop(1);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
out_return_error:
|
||||||
|
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
||||||
|
+ pthread_testcancel();
|
||||||
|
+
|
||||||
|
do_error_downcall(fd, uid, downcall_err);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
@@ -782,36 +840,69 @@ void free_upcall_info(struct clnt_upcall
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
-gssd_work_thread_fn(struct clnt_upcall_info *info)
|
||||||
|
+cleanup_clnt_upcall_info(void *arg)
|
||||||
|
{
|
||||||
|
- process_krb5_upcall(info->clp, info->uid, info->fd, info->srchost, info->target, info->service);
|
||||||
|
+ struct clnt_upcall_info *info = (struct clnt_upcall_info *)arg;
|
||||||
|
+
|
||||||
|
free_upcall_info(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+gssd_work_thread_fn(struct clnt_upcall_info *info)
|
||||||
|
+{
|
||||||
|
+ pthread_cleanup_push(cleanup_clnt_upcall_info, info);
|
||||||
|
+ process_krb5_upcall(info);
|
||||||
|
+ pthread_cleanup_pop(1);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct upcall_thread_info *
|
||||||
|
+alloc_upcall_thread_info(void)
|
||||||
|
+{
|
||||||
|
+ struct upcall_thread_info *info;
|
||||||
|
+
|
||||||
|
+ info = malloc(sizeof(struct upcall_thread_info));
|
||||||
|
+ if (info == NULL)
|
||||||
|
+ return NULL;
|
||||||
|
+ memset(info, 0, sizeof(*info));
|
||||||
|
+ return info;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
-start_upcall_thread(void (*func)(struct clnt_upcall_info *), void *info)
|
||||||
|
+start_upcall_thread(void (*func)(struct clnt_upcall_info *), struct clnt_upcall_info *info)
|
||||||
|
{
|
||||||
|
pthread_attr_t attr;
|
||||||
|
pthread_t th;
|
||||||
|
+ struct upcall_thread_info *tinfo;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
+ tinfo = alloc_upcall_thread_info();
|
||||||
|
+ if (!tinfo)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+ tinfo->fd = info->fd;
|
||||||
|
+ tinfo->uid = info->uid;
|
||||||
|
+
|
||||||
|
ret = pthread_attr_init(&attr);
|
||||||
|
if (ret != 0) {
|
||||||
|
printerr(0, "ERROR: failed to init pthread attr: ret %d: %s\n",
|
||||||
|
ret, strerror(errno));
|
||||||
|
- return ret;
|
||||||
|
- }
|
||||||
|
- ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||||
|
- if (ret != 0) {
|
||||||
|
- printerr(0, "ERROR: failed to create pthread attr: ret %d: "
|
||||||
|
- "%s\n", ret, strerror(errno));
|
||||||
|
+ free(tinfo);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = pthread_create(&th, &attr, (void *)func, (void *)info);
|
||||||
|
- if (ret != 0)
|
||||||
|
+ if (ret != 0) {
|
||||||
|
printerr(0, "ERROR: pthread_create failed: ret %d: %s\n",
|
||||||
|
ret, strerror(errno));
|
||||||
|
+ free(tinfo);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+ tinfo->tid = th;
|
||||||
|
+ pthread_mutex_lock(&active_thread_list_lock);
|
||||||
|
+ clock_gettime(CLOCK_MONOTONIC, &tinfo->timeout);
|
||||||
|
+ tinfo->timeout.tv_sec += upcall_timeout;
|
||||||
|
+ TAILQ_INSERT_TAIL(&active_thread_list, tinfo, list);
|
||||||
|
+ pthread_mutex_unlock(&active_thread_list_lock);
|
||||||
|
+
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
12
SOURCES/nfs-utils-2.3.3-idmap-errmsg.patch
Normal file
12
SOURCES/nfs-utils-2.3.3-idmap-errmsg.patch
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
diff -up nfs-utils-2.3.3/utils/nfsidmap/nfsidmap.c.orig nfs-utils-2.3.3/utils/nfsidmap/nfsidmap.c
|
||||||
|
--- nfs-utils-2.3.3/utils/nfsidmap/nfsidmap.c.orig 2020-05-05 14:07:24.642693179 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/nfsidmap/nfsidmap.c 2020-05-05 14:08:39.054849153 -0400
|
||||||
|
@@ -432,7 +432,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
|
xlog_stderr(verbose);
|
||||||
|
if ((argc - optind) != 2) {
|
||||||
|
- xlog_warn("Bad arg count. Check /etc/request-key.conf");
|
||||||
|
+ xlog_warn("Bad arg count. Check /etc/request-key.d/request-key.conf");
|
||||||
|
xlog_warn(USAGE, progname);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
57
SOURCES/nfs-utils-2.3.3-junction-err-fix.patch
Normal file
57
SOURCES/nfs-utils-2.3.3-junction-err-fix.patch
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
commit efefa7845601f551820fa17cb0808dbb3c3cc3dd
|
||||||
|
Author: Steve Dickson <steved@redhat.com>
|
||||||
|
Date: Wed Nov 13 09:32:00 2019 -0500
|
||||||
|
|
||||||
|
junction: Fixed debug statement to compile with -Werror=format=2 flag
|
||||||
|
|
||||||
|
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/support/junction/xml.c b/support/junction/xml.c
|
||||||
|
index 79b0770..7005e95 100644
|
||||||
|
--- a/support/junction/xml.c
|
||||||
|
+++ b/support/junction/xml.c
|
||||||
|
@@ -327,8 +327,8 @@ junction_parse_xml_read(const char *pathname, int fd, const char *name,
|
||||||
|
if (retval != FEDFS_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
- xlog(D_CALL, "%s: XML document contained in junction:\n%.*s",
|
||||||
|
- __func__, len, buf);
|
||||||
|
+ xlog(D_CALL, "%s: XML document contained in junction:\n%ld.%s",
|
||||||
|
+ __func__, len, (char *)buf);
|
||||||
|
|
||||||
|
retval = junction_parse_xml_buf(pathname, name, buf, len, doc);
|
||||||
|
|
||||||
|
commit f7c0c0dc4a02d87965d3fbbab69786ca07fdecea
|
||||||
|
Author: Guillaume Rousse <guillomovitch@gmail.com>
|
||||||
|
Date: Fri Nov 22 10:20:03 2019 -0500
|
||||||
|
|
||||||
|
fix compilation with -Werror=format on i586
|
||||||
|
|
||||||
|
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/support/junction/xml.c b/support/junction/xml.c
|
||||||
|
index 7005e95..813110b 100644
|
||||||
|
--- a/support/junction/xml.c
|
||||||
|
+++ b/support/junction/xml.c
|
||||||
|
@@ -327,7 +327,7 @@ junction_parse_xml_read(const char *pathname, int fd, const char *name,
|
||||||
|
if (retval != FEDFS_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
- xlog(D_CALL, "%s: XML document contained in junction:\n%ld.%s",
|
||||||
|
+ xlog(D_CALL, "%s: XML document contained in junction:\n%zu.%s",
|
||||||
|
__func__, len, (char *)buf);
|
||||||
|
|
||||||
|
retval = junction_parse_xml_buf(pathname, name, buf, len, doc);
|
||||||
|
diff --git a/tools/locktest/testlk.c b/tools/locktest/testlk.c
|
||||||
|
index b392f71..ea51f78 100644
|
||||||
|
--- a/tools/locktest/testlk.c
|
||||||
|
+++ b/tools/locktest/testlk.c
|
||||||
|
@@ -81,7 +81,7 @@ main(int argc, char **argv)
|
||||||
|
if (fl.l_type == F_UNLCK) {
|
||||||
|
printf("%s: no conflicting lock\n", fname);
|
||||||
|
} else {
|
||||||
|
- printf("%s: conflicting lock by %d on (%ld;%ld)\n",
|
||||||
|
+ printf("%s: conflicting lock by %d on (%zd;%zd)\n",
|
||||||
|
fname, fl.l_pid, fl.l_start, fl.l_len);
|
||||||
|
}
|
||||||
|
return 0;
|
14
SOURCES/nfs-utils-2.3.3-mount-ebusy.patch
Normal file
14
SOURCES/nfs-utils-2.3.3-mount-ebusy.patch
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
diff -up nfs-utils-2.3.3/utils/mount/stropts.c.orig nfs-utils-2.3.3/utils/mount/stropts.c
|
||||||
|
--- nfs-utils-2.3.3/utils/mount/stropts.c.orig 2022-02-14 11:28:51.570084952 -0500
|
||||||
|
+++ nfs-utils-2.3.3/utils/mount/stropts.c 2022-02-14 11:29:16.174450628 -0500
|
||||||
|
@@ -966,7 +966,9 @@ fall_back:
|
||||||
|
if ((result = nfs_try_mount_v3v2(mi, FALSE)))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
- errno = olderrno;
|
||||||
|
+ if (errno != EBUSY && errno != EACCES)
|
||||||
|
+ errno = olderrno;
|
||||||
|
+
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
116
SOURCES/nfs-utils-2.3.3-mount-sloppy.patch
Normal file
116
SOURCES/nfs-utils-2.3.3-mount-sloppy.patch
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
diff -up nfs-utils-2.3.3/utils/mount/nfs.man.save nfs-utils-2.3.3/utils/mount/nfs.man
|
||||||
|
--- nfs-utils-2.3.3/utils/mount/nfs.man.save 2021-07-28 14:42:20.977740892 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/mount/nfs.man 2021-07-28 14:42:01.133212815 -0400
|
||||||
|
@@ -525,6 +525,13 @@ using the FS-Cache facility. See cachefi
|
||||||
|
and <kernel_soruce>/Documentation/filesystems/caching
|
||||||
|
for detail on how to configure the FS-Cache facility.
|
||||||
|
Default value is nofsc.
|
||||||
|
+.TP 1.5i
|
||||||
|
+.B sloppy
|
||||||
|
+The
|
||||||
|
+.B sloppy
|
||||||
|
+option is an alternative to specifying
|
||||||
|
+.BR mount.nfs " -s " option.
|
||||||
|
+
|
||||||
|
.SS "Options for NFS versions 2 and 3 only"
|
||||||
|
Use these options, along with the options in the above subsection,
|
||||||
|
for NFS versions 2 and 3 only.
|
||||||
|
diff -up nfs-utils-2.3.3/utils/mount/parse_opt.c.save nfs-utils-2.3.3/utils/mount/parse_opt.c
|
||||||
|
--- nfs-utils-2.3.3/utils/mount/parse_opt.c.save 2021-07-28 14:40:15.467400995 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/mount/parse_opt.c 2021-07-28 14:39:57.666927309 -0400
|
||||||
|
@@ -178,6 +178,22 @@ static void options_tail_insert(struct m
|
||||||
|
options->count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void options_head_insert(struct mount_options *options,
|
||||||
|
+ struct mount_option *option)
|
||||||
|
+{
|
||||||
|
+ struct mount_option *ohead = options->head;
|
||||||
|
+
|
||||||
|
+ option->prev = NULL;
|
||||||
|
+ option->next = ohead;
|
||||||
|
+ if (ohead)
|
||||||
|
+ ohead->prev = option;
|
||||||
|
+ else
|
||||||
|
+ options->tail = option;
|
||||||
|
+ options->head = option;
|
||||||
|
+
|
||||||
|
+ options->count++;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void options_delete(struct mount_options *options,
|
||||||
|
struct mount_option *option)
|
||||||
|
{
|
||||||
|
@@ -374,6 +390,23 @@ po_return_t po_join(struct mount_options
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
+ * po_insert - insert an option into a group of options
|
||||||
|
+ * @options: pointer to mount options
|
||||||
|
+ * @option: pointer to a C string containing the option to add
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+po_return_t po_insert(struct mount_options *options, char *str)
|
||||||
|
+{
|
||||||
|
+ struct mount_option *option = option_create(str);
|
||||||
|
+
|
||||||
|
+ if (option) {
|
||||||
|
+ options_head_insert(options, option);
|
||||||
|
+ return PO_SUCCEEDED;
|
||||||
|
+ }
|
||||||
|
+ return PO_FAILED;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
* po_append - concatenate an option onto a group of options
|
||||||
|
* @options: pointer to mount options
|
||||||
|
* @option: pointer to a C string containing the option to add
|
||||||
|
diff -up nfs-utils-2.3.3/utils/mount/parse_opt.h.save nfs-utils-2.3.3/utils/mount/parse_opt.h
|
||||||
|
--- nfs-utils-2.3.3/utils/mount/parse_opt.h.save 2021-07-28 14:40:54.292434148 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/mount/parse_opt.h 2021-07-28 14:39:57.666927309 -0400
|
||||||
|
@@ -43,6 +43,7 @@ void po_replace(struct mount_options *
|
||||||
|
struct mount_options *);
|
||||||
|
po_return_t po_join(struct mount_options *, char **);
|
||||||
|
|
||||||
|
+po_return_t po_insert(struct mount_options *, char *);
|
||||||
|
po_return_t po_append(struct mount_options *, char *);
|
||||||
|
po_found_t po_contains(struct mount_options *, char *);
|
||||||
|
po_found_t po_contains_prefix(struct mount_options *options,
|
||||||
|
diff -up nfs-utils-2.3.3/utils/mount/stropts.c.save nfs-utils-2.3.3/utils/mount/stropts.c
|
||||||
|
--- nfs-utils-2.3.3/utils/mount/stropts.c.save 2021-07-28 14:41:14.842981010 -0400
|
||||||
|
+++ nfs-utils-2.3.3/utils/mount/stropts.c 2021-07-28 14:42:01.134212842 -0400
|
||||||
|
@@ -336,13 +336,21 @@ static int nfs_verify_lock_option(struct
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int nfs_append_sloppy_option(struct mount_options *options)
|
||||||
|
+static int nfs_insert_sloppy_option(struct mount_options *options)
|
||||||
|
{
|
||||||
|
- if (!sloppy || linux_version_code() < MAKE_VERSION(2, 6, 27))
|
||||||
|
+ if (linux_version_code() < MAKE_VERSION(2, 6, 27))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
- if (po_append(options, "sloppy") == PO_FAILED)
|
||||||
|
- return 0;
|
||||||
|
+ if (po_contains(options, "sloppy")) {
|
||||||
|
+ po_remove_all(options, "sloppy");
|
||||||
|
+ sloppy++;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (sloppy) {
|
||||||
|
+ if (po_insert(options, "sloppy") == PO_FAILED)
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -424,7 +432,7 @@ static int nfs_validate_options(struct n
|
||||||
|
if (!nfs_set_version(mi))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
- if (!nfs_append_sloppy_option(mi->options))
|
||||||
|
+ if (!nfs_insert_sloppy_option(mi->options))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
61
SOURCES/nfs-utils-2.3.3-mountd-pseudofs.patch
Normal file
61
SOURCES/nfs-utils-2.3.3-mountd-pseudofs.patch
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
diff --git a/utils/mountd/v4root.c b/utils/mountd/v4root.c
|
||||||
|
index d735dbfe..8ec33fb0 100644
|
||||||
|
--- a/utils/mountd/v4root.c
|
||||||
|
+++ b/utils/mountd/v4root.c
|
||||||
|
@@ -36,9 +36,9 @@ static nfs_export pseudo_root = {
|
||||||
|
.m_export = {
|
||||||
|
.e_hostname = "*",
|
||||||
|
.e_path = "/",
|
||||||
|
- .e_flags = NFSEXP_READONLY | NFSEXP_ROOTSQUASH
|
||||||
|
+ .e_flags = NFSEXP_READONLY
|
||||||
|
| NFSEXP_NOSUBTREECHECK | NFSEXP_FSID
|
||||||
|
- | NFSEXP_V4ROOT,
|
||||||
|
+ | NFSEXP_V4ROOT | NFSEXP_INSECURE_PORT,
|
||||||
|
.e_anonuid = 65534,
|
||||||
|
.e_anongid = 65534,
|
||||||
|
.e_squids = NULL,
|
||||||
|
@@ -57,15 +57,11 @@ static nfs_export pseudo_root = {
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
-set_pseudofs_security(struct exportent *pseudo, int flags)
|
||||||
|
+set_pseudofs_security(struct exportent *pseudo)
|
||||||
|
{
|
||||||
|
struct flav_info *flav;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
- if (flags & NFSEXP_INSECURE_PORT)
|
||||||
|
- pseudo->e_flags |= NFSEXP_INSECURE_PORT;
|
||||||
|
- if ((flags & NFSEXP_ROOTSQUASH) == 0)
|
||||||
|
- pseudo->e_flags &= ~NFSEXP_ROOTSQUASH;
|
||||||
|
for (flav = flav_map; flav < flav_map + flav_map_size; flav++) {
|
||||||
|
struct sec_entry *new;
|
||||||
|
|
||||||
|
@@ -75,8 +71,7 @@ set_pseudofs_security(struct exportent *pseudo, int flags)
|
||||||
|
i = secinfo_addflavor(flav, pseudo);
|
||||||
|
new = &pseudo->e_secinfo[i];
|
||||||
|
|
||||||
|
- if (flags & NFSEXP_INSECURE_PORT)
|
||||||
|
- new->flags |= NFSEXP_INSECURE_PORT;
|
||||||
|
+ new->flags |= NFSEXP_INSECURE_PORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -95,7 +90,7 @@ v4root_create(char *path, nfs_export *export)
|
||||||
|
strncpy(eep.e_path, path, sizeof(eep.e_path)-1);
|
||||||
|
if (strcmp(path, "/") != 0)
|
||||||
|
eep.e_flags &= ~NFSEXP_FSID;
|
||||||
|
- set_pseudofs_security(&eep, curexp->e_flags);
|
||||||
|
+ set_pseudofs_security(&eep);
|
||||||
|
exp = export_create(&eep, 0);
|
||||||
|
if (exp == NULL)
|
||||||
|
return NULL;
|
||||||
|
@@ -143,7 +138,7 @@ pseudofs_update(char *hostname, char *path, nfs_export *source)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Update an existing V4ROOT export: */
|
||||||
|
- set_pseudofs_security(&exp->m_export, source->m_export.e_flags);
|
||||||
|
+ set_pseudofs_security(&exp->m_export);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
976
SOURCES/nfs-utils-2.3.3-mountd-v4-logging.patch
Normal file
976
SOURCES/nfs-utils-2.3.3-mountd-v4-logging.patch
Normal file
@ -0,0 +1,976 @@
|
|||||||
|
diff --git a/nfs.conf b/nfs.conf
|
||||||
|
index 05247ff9..86ed7d53 100644
|
||||||
|
--- a/nfs.conf
|
||||||
|
+++ b/nfs.conf
|
||||||
|
@@ -38,6 +38,8 @@ use-gss-proxy=1
|
||||||
|
# reverse-lookup=n
|
||||||
|
# state-directory-path=/var/lib/nfs
|
||||||
|
# ha-callout=
|
||||||
|
+# cache-use-ipaddr=n
|
||||||
|
+# ttl=1800
|
||||||
|
#
|
||||||
|
[nfsdcld]
|
||||||
|
# debug=0
|
||||||
|
diff --git a/support/export/Makefile.am b/support/export/Makefile.am
|
||||||
|
index 13f7a49c..d6ee502f 100644
|
||||||
|
--- a/support/export/Makefile.am
|
||||||
|
+++ b/support/export/Makefile.am
|
||||||
|
@@ -11,7 +11,8 @@ EXTRA_DIST = mount.x
|
||||||
|
|
||||||
|
noinst_LIBRARIES = libexport.a
|
||||||
|
libexport_a_SOURCES = client.c export.c hostname.c \
|
||||||
|
- xtab.c mount_clnt.c mount_xdr.c
|
||||||
|
+ xtab.c mount_clnt.c mount_xdr.c \
|
||||||
|
+ cache.c auth.c v4root.c v4clients.c
|
||||||
|
BUILT_SOURCES = $(GENFILES)
|
||||||
|
|
||||||
|
noinst_HEADERS = mount.h
|
||||||
|
diff --git a/utils/mountd/auth.c b/support/export/auth.c
|
||||||
|
similarity index 98%
|
||||||
|
rename from utils/mountd/auth.c
|
||||||
|
rename to support/export/auth.c
|
||||||
|
index 8299256e..73ad6f73 100644
|
||||||
|
--- a/utils/mountd/auth.c
|
||||||
|
+++ b/support/export/auth.c
|
||||||
|
@@ -22,7 +22,7 @@
|
||||||
|
#include "misc.h"
|
||||||
|
#include "nfslib.h"
|
||||||
|
#include "exportfs.h"
|
||||||
|
-#include "mountd.h"
|
||||||
|
+#include "export.h"
|
||||||
|
#include "v4root.h"
|
||||||
|
|
||||||
|
enum auth_error
|
||||||
|
@@ -43,11 +43,13 @@ extern int use_ipaddr;
|
||||||
|
|
||||||
|
extern struct state_paths etab;
|
||||||
|
|
||||||
|
+/*
|
||||||
|
void
|
||||||
|
auth_init(void)
|
||||||
|
{
|
||||||
|
auth_reload();
|
||||||
|
}
|
||||||
|
+*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A client can match many different netgroups and it's tough to know
|
||||||
|
@@ -64,6 +66,10 @@ check_useipaddr(void)
|
||||||
|
int old_use_ipaddr = use_ipaddr;
|
||||||
|
unsigned int len = 0;
|
||||||
|
|
||||||
|
+ if (use_ipaddr > 1)
|
||||||
|
+ /* fixed - don't check */
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
/* add length of m_hostname + 1 for the comma */
|
||||||
|
for (clp = clientlist[MCL_NETGROUP]; clp; clp = clp->m_next)
|
||||||
|
len += (strlen(clp->m_hostname) + 1);
|
||||||
|
diff --git a/utils/mountd/cache.c b/support/export/cache.c
|
||||||
|
similarity index 95%
|
||||||
|
rename from utils/mountd/cache.c
|
||||||
|
rename to support/export/cache.c
|
||||||
|
index c73e29be..98d50828 100644
|
||||||
|
--- a/utils/mountd/cache.c
|
||||||
|
+++ b/support/export/cache.c
|
||||||
|
@@ -29,21 +29,18 @@
|
||||||
|
#include "misc.h"
|
||||||
|
#include "nfslib.h"
|
||||||
|
#include "exportfs.h"
|
||||||
|
-#include "mountd.h"
|
||||||
|
-#include "fsloc.h"
|
||||||
|
+#include "export.h"
|
||||||
|
#include "pseudoflavors.h"
|
||||||
|
#include "xcommon.h"
|
||||||
|
|
||||||
|
+#ifdef HAVE_JUNCTION_SUPPORT
|
||||||
|
+#include "../../utils/mountd/fsloc.h"
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
#ifdef USE_BLKID
|
||||||
|
#include "blkid/blkid.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-/*
|
||||||
|
- * Invoked by RPC service loop
|
||||||
|
- */
|
||||||
|
-void cache_set_fds(fd_set *fdset);
|
||||||
|
-int cache_process_req(fd_set *readfds);
|
||||||
|
-
|
||||||
|
enum nfsd_fsid {
|
||||||
|
FSID_DEV = 0,
|
||||||
|
FSID_NUM,
|
||||||
|
@@ -63,7 +60,6 @@ enum nfsd_fsid {
|
||||||
|
* Record is terminated with newline.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
-static int cache_export_ent(char *buf, int buflen, char *domain, struct exportent *exp, char *path);
|
||||||
|
|
||||||
|
#define INITIAL_MANAGED_GROUPS 100
|
||||||
|
|
||||||
|
@@ -81,6 +77,7 @@ static void auth_unix_ip(int f)
|
||||||
|
char class[20];
|
||||||
|
char ipaddr[INET6_ADDRSTRLEN + 1];
|
||||||
|
char *client = NULL;
|
||||||
|
+ struct addrinfo *ai = NULL;
|
||||||
|
struct addrinfo *tmp = NULL;
|
||||||
|
char buf[RPC_CHAN_BUF_SIZE], *bp;
|
||||||
|
int blen;
|
||||||
|
@@ -106,21 +103,26 @@ static void auth_unix_ip(int f)
|
||||||
|
|
||||||
|
auth_reload();
|
||||||
|
|
||||||
|
- /* addr is a valid, interesting address, find the domain name... */
|
||||||
|
- if (!use_ipaddr) {
|
||||||
|
- struct addrinfo *ai = NULL;
|
||||||
|
-
|
||||||
|
- ai = client_resolve(tmp->ai_addr);
|
||||||
|
- if (ai) {
|
||||||
|
- client = client_compose(ai);
|
||||||
|
- freeaddrinfo(ai);
|
||||||
|
- }
|
||||||
|
+ /* addr is a valid address, find the domain name... */
|
||||||
|
+ ai = client_resolve(tmp->ai_addr);
|
||||||
|
+ if (ai) {
|
||||||
|
+ client = client_compose(ai);
|
||||||
|
+ freeaddrinfo(ai);
|
||||||
|
}
|
||||||
|
+ if (!client)
|
||||||
|
+ xlog(D_AUTH, "failed authentication for IP %s", ipaddr);
|
||||||
|
+ else if (!use_ipaddr)
|
||||||
|
+ xlog(D_AUTH, "successful authentication for IP %s as %s",
|
||||||
|
+ ipaddr, *client ? client : "DEFAULT");
|
||||||
|
+ else
|
||||||
|
+ xlog(D_AUTH, "successful authentication for IP %s",
|
||||||
|
+ ipaddr);
|
||||||
|
+
|
||||||
|
bp = buf; blen = sizeof(buf);
|
||||||
|
qword_add(&bp, &blen, "nfsd");
|
||||||
|
qword_add(&bp, &blen, ipaddr);
|
||||||
|
- qword_adduint(&bp, &blen, time(0) + DEFAULT_TTL);
|
||||||
|
- if (use_ipaddr) {
|
||||||
|
+ qword_adduint(&bp, &blen, time(0) + default_ttl);
|
||||||
|
+ if (use_ipaddr && client) {
|
||||||
|
memmove(ipaddr + 1, ipaddr, strlen(ipaddr) + 1);
|
||||||
|
ipaddr[0] = '$';
|
||||||
|
qword_add(&bp, &blen, ipaddr);
|
||||||
|
@@ -192,7 +194,7 @@ static void auth_unix_gid(int f)
|
||||||
|
|
||||||
|
bp = buf; blen = sizeof(buf);
|
||||||
|
qword_adduint(&bp, &blen, uid);
|
||||||
|
- qword_adduint(&bp, &blen, time(0) + DEFAULT_TTL);
|
||||||
|
+ qword_adduint(&bp, &blen, time(0) + default_ttl);
|
||||||
|
if (rv >= 0) {
|
||||||
|
qword_adduint(&bp, &blen, ngroups);
|
||||||
|
for (i=0; i<ngroups; i++)
|
||||||
|
@@ -688,7 +690,6 @@ static void nfsd_fh(int f)
|
||||||
|
char *found_path = NULL;
|
||||||
|
nfs_export *exp;
|
||||||
|
int i;
|
||||||
|
- int dev_missing = 0;
|
||||||
|
char buf[RPC_CHAN_BUF_SIZE], *bp;
|
||||||
|
int blen;
|
||||||
|
|
||||||
|
@@ -755,11 +756,6 @@ static void nfsd_fh(int f)
|
||||||
|
if (!is_ipaddr_client(dom)
|
||||||
|
&& !namelist_client_matches(exp, dom))
|
||||||
|
continue;
|
||||||
|
- if (exp->m_export.e_mountpoint &&
|
||||||
|
- !is_mountpoint(exp->m_export.e_mountpoint[0]?
|
||||||
|
- exp->m_export.e_mountpoint:
|
||||||
|
- exp->m_export.e_path))
|
||||||
|
- dev_missing ++;
|
||||||
|
|
||||||
|
if (!match_fsid(&parsed, exp, path))
|
||||||
|
continue;
|
||||||
|
@@ -794,7 +790,7 @@ static void nfsd_fh(int f)
|
||||||
|
!is_mountpoint(found->e_mountpoint[0]?
|
||||||
|
found->e_mountpoint:
|
||||||
|
found->e_path)) {
|
||||||
|
- /* Cannot export this yet
|
||||||
|
+ /* Cannot export this yet
|
||||||
|
* should log a warning, but need to rate limit
|
||||||
|
xlog(L_WARNING, "%s not exported as %d not a mountpoint",
|
||||||
|
found->e_path, found->e_mountpoint);
|
||||||
|
@@ -802,16 +798,6 @@ static void nfsd_fh(int f)
|
||||||
|
/* FIXME we need to make sure we re-visit this later */
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
- if (!found && dev_missing) {
|
||||||
|
- /* The missing dev could be what we want, so just be
|
||||||
|
- * quite rather than returning stale yet
|
||||||
|
- */
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (found)
|
||||||
|
- if (cache_export_ent(buf, sizeof(buf), dom, found, found_path) < 0)
|
||||||
|
- found = 0;
|
||||||
|
|
||||||
|
bp = buf; blen = sizeof(buf);
|
||||||
|
qword_add(&bp, &blen, dom);
|
||||||
|
@@ -831,6 +817,8 @@ static void nfsd_fh(int f)
|
||||||
|
qword_addeol(&bp, &blen);
|
||||||
|
if (blen <= 0 || write(f, buf, bp - buf) != bp - buf)
|
||||||
|
xlog(L_ERROR, "nfsd_fh: error writing reply");
|
||||||
|
+ if (!found)
|
||||||
|
+ xlog(D_AUTH, "denied access to %s", *dom == '$' ? dom+1 : dom);
|
||||||
|
out:
|
||||||
|
if (found_path)
|
||||||
|
free(found_path);
|
||||||
|
@@ -839,6 +827,7 @@ out:
|
||||||
|
xlog(D_CALL, "nfsd_fh: found %p path %s", found, found ? found->e_path : NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef HAVE_JUNCTION_SUPPORT
|
||||||
|
static void write_fsloc(char **bp, int *blen, struct exportent *ep)
|
||||||
|
{
|
||||||
|
struct servers *servers;
|
||||||
|
@@ -861,7 +850,7 @@ static void write_fsloc(char **bp, int *blen, struct exportent *ep)
|
||||||
|
qword_addint(bp, blen, servers->h_referral);
|
||||||
|
release_replicas(servers);
|
||||||
|
}
|
||||||
|
-
|
||||||
|
+#endif
|
||||||
|
static void write_secinfo(char **bp, int *blen, struct exportent *ep, int flag_mask)
|
||||||
|
{
|
||||||
|
struct sec_entry *p;
|
||||||
|
@@ -890,7 +879,7 @@ static int dump_to_cache(int f, char *buf, int buflen, char *domain,
|
||||||
|
time_t now = time(0);
|
||||||
|
|
||||||
|
if (ttl <= 1)
|
||||||
|
- ttl = DEFAULT_TTL;
|
||||||
|
+ ttl = default_ttl;
|
||||||
|
|
||||||
|
qword_add(&bp, &blen, domain);
|
||||||
|
qword_add(&bp, &blen, path);
|
||||||
|
@@ -903,7 +892,10 @@ static int dump_to_cache(int f, char *buf, int buflen, char *domain,
|
||||||
|
qword_addint(&bp, &blen, exp->e_anonuid);
|
||||||
|
qword_addint(&bp, &blen, exp->e_anongid);
|
||||||
|
qword_addint(&bp, &blen, exp->e_fsid);
|
||||||
|
+
|
||||||
|
+#ifdef HAVE_JUNCTION_SUPPORT
|
||||||
|
write_fsloc(&bp, &blen, exp);
|
||||||
|
+#endif
|
||||||
|
write_secinfo(&bp, &blen, exp, flag_mask);
|
||||||
|
if (exp->e_uuid == NULL || different_fs) {
|
||||||
|
char u[16];
|
||||||
|
@@ -917,8 +909,13 @@ static int dump_to_cache(int f, char *buf, int buflen, char *domain,
|
||||||
|
qword_add(&bp, &blen, "uuid");
|
||||||
|
qword_addhex(&bp, &blen, u, 16);
|
||||||
|
}
|
||||||
|
- } else
|
||||||
|
+ xlog(D_AUTH, "granted access to %s for %s",
|
||||||
|
+ path, *domain == '$' ? domain+1 : domain);
|
||||||
|
+ } else {
|
||||||
|
qword_adduint(&bp, &blen, now + ttl);
|
||||||
|
+ xlog(D_AUTH, "denied access to %s for %s",
|
||||||
|
+ path, *domain == '$' ? domain+1 : domain);
|
||||||
|
+ }
|
||||||
|
qword_addeol(&bp, &blen);
|
||||||
|
if (blen <= 0) return -1;
|
||||||
|
if (write(f, buf, bp - buf) != bp - buf) return -1;
|
||||||
|
@@ -1421,6 +1418,40 @@ int cache_process_req(fd_set *readfds)
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/**
|
||||||
|
+ * cache_process_loop - process incoming upcalls
|
||||||
|
+ */
|
||||||
|
+void cache_process_loop(void)
|
||||||
|
+{
|
||||||
|
+ fd_set readfds;
|
||||||
|
+ int selret;
|
||||||
|
+
|
||||||
|
+ FD_ZERO(&readfds);
|
||||||
|
+
|
||||||
|
+ for (;;) {
|
||||||
|
+
|
||||||
|
+ cache_set_fds(&readfds);
|
||||||
|
+ v4clients_set_fds(&readfds);
|
||||||
|
+
|
||||||
|
+ selret = select(FD_SETSIZE, &readfds,
|
||||||
|
+ (void *) 0, (void *) 0, (struct timeval *) 0);
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ switch (selret) {
|
||||||
|
+ case -1:
|
||||||
|
+ if (errno == EINTR || errno == ECONNREFUSED
|
||||||
|
+ || errno == ENETUNREACH || errno == EHOSTUNREACH)
|
||||||
|
+ continue;
|
||||||
|
+ xlog(L_ERROR, "my_svc_run() - select: %m");
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ default:
|
||||||
|
+ cache_process_req(&readfds);
|
||||||
|
+ v4clients_process(&readfds);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Give IP->domain and domain+path->options to kernel
|
||||||
|
diff --git a/support/export/export.h b/support/export/export.h
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..8d5a0d30
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/support/export/export.h
|
||||||
|
@@ -0,0 +1,41 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (C) 2021 Red Hat <nfs@redhat.com>
|
||||||
|
+ *
|
||||||
|
+ * support/export/export.h
|
||||||
|
+ *
|
||||||
|
+ * Declarations for export support
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#ifndef EXPORT_H
|
||||||
|
+#define EXPORT_H
|
||||||
|
+
|
||||||
|
+#include "nfslib.h"
|
||||||
|
+#include "exportfs.h"
|
||||||
|
+
|
||||||
|
+unsigned int auth_reload(void);
|
||||||
|
+nfs_export * auth_authenticate(const char *what,
|
||||||
|
+ const struct sockaddr *caller,
|
||||||
|
+ const char *path);
|
||||||
|
+
|
||||||
|
+void cache_open(void);
|
||||||
|
+void cache_set_fds(fd_set *fdset);
|
||||||
|
+int cache_process_req(fd_set *readfds);
|
||||||
|
+void cache_process_loop(void);
|
||||||
|
+
|
||||||
|
+void v4clients_init(void);
|
||||||
|
+void v4clients_set_fds(fd_set *fdset);
|
||||||
|
+int v4clients_process(fd_set *fdset);
|
||||||
|
+
|
||||||
|
+struct nfs_fh_len *
|
||||||
|
+ cache_get_filehandle(nfs_export *exp, int len, char *p);
|
||||||
|
+int cache_export(nfs_export *exp, char *path);
|
||||||
|
+
|
||||||
|
+bool ipaddr_client_matches(nfs_export *exp, struct addrinfo *ai);
|
||||||
|
+bool namelist_client_matches(nfs_export *exp, char *dom);
|
||||||
|
+bool client_matches(nfs_export *exp, char *dom, struct addrinfo *ai);
|
||||||
|
+
|
||||||
|
+static inline bool is_ipaddr_client(char *dom)
|
||||||
|
+{
|
||||||
|
+ return dom[0] == '$';
|
||||||
|
+}
|
||||||
|
+#endif /* EXPORT__H */
|
||||||
|
diff --git a/support/export/v4clients.c b/support/export/v4clients.c
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..dd985463
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/support/export/v4clients.c
|
||||||
|
@@ -0,0 +1,227 @@
|
||||||
|
+/*
|
||||||
|
+ * support/export/v4clients.c
|
||||||
|
+ *
|
||||||
|
+ * Montior clients appearing in, and disappearing from, /proc/fs/nfsd/clients
|
||||||
|
+ * and log relevant information.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <unistd.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <sys/inotify.h>
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include "export.h"
|
||||||
|
+
|
||||||
|
+/* search.h declares 'struct entry' and nfs_prot.h
|
||||||
|
+ * does too. Easiest fix is to trick search.h into
|
||||||
|
+ * calling its struct "struct Entry".
|
||||||
|
+ */
|
||||||
|
+#define entry Entry
|
||||||
|
+#include <search.h>
|
||||||
|
+#undef entry
|
||||||
|
+
|
||||||
|
+static int clients_fd = -1;
|
||||||
|
+
|
||||||
|
+void v4clients_init(void)
|
||||||
|
+{
|
||||||
|
+ if (clients_fd >= 0)
|
||||||
|
+ return;
|
||||||
|
+ clients_fd = inotify_init1(IN_NONBLOCK);
|
||||||
|
+ if (clients_fd < 0) {
|
||||||
|
+ xlog_err("Unable to initialise v4clients watcher: %s\n",
|
||||||
|
+ strerror(errno));
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ if (inotify_add_watch(clients_fd, "/proc/fs/nfsd/clients",
|
||||||
|
+ IN_CREATE | IN_DELETE) < 0) {
|
||||||
|
+ xlog_err("Unable to watch /proc/fs/nfsd/clients: %s\n",
|
||||||
|
+ strerror(errno));
|
||||||
|
+ close(clients_fd);
|
||||||
|
+ clients_fd = -1;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void v4clients_set_fds(fd_set *fdset)
|
||||||
|
+{
|
||||||
|
+ if (clients_fd >= 0)
|
||||||
|
+ FD_SET(clients_fd, fdset);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void *tree_root;
|
||||||
|
+static int have_unconfirmed;
|
||||||
|
+
|
||||||
|
+struct ent {
|
||||||
|
+ unsigned long num;
|
||||||
|
+ char *clientid;
|
||||||
|
+ char *addr;
|
||||||
|
+ int vers;
|
||||||
|
+ int unconfirmed;
|
||||||
|
+ int wid;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int ent_cmp(const void *av, const void *bv)
|
||||||
|
+{
|
||||||
|
+ const struct ent *a = av;
|
||||||
|
+ const struct ent *b = bv;
|
||||||
|
+
|
||||||
|
+ if (a->num < b->num)
|
||||||
|
+ return -1;
|
||||||
|
+ if (a->num > b->num)
|
||||||
|
+ return 1;
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void free_ent(struct ent *ent)
|
||||||
|
+{
|
||||||
|
+ free(ent->clientid);
|
||||||
|
+ free(ent->addr);
|
||||||
|
+ free(ent);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static char *dup_line(char *line)
|
||||||
|
+{
|
||||||
|
+ char *ret;
|
||||||
|
+ char *e = strchr(line, '\n');
|
||||||
|
+ if (!e)
|
||||||
|
+ e = line + strlen(line);
|
||||||
|
+ ret = malloc(e - line + 1);
|
||||||
|
+ if (ret) {
|
||||||
|
+ memcpy(ret, line, e - line);
|
||||||
|
+ ret[e-line] = 0;
|
||||||
|
+ }
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void read_info(struct ent *key)
|
||||||
|
+{
|
||||||
|
+ char buf[2048];
|
||||||
|
+ char *path;
|
||||||
|
+ int was_unconfirmed = key->unconfirmed;
|
||||||
|
+ FILE *f;
|
||||||
|
+
|
||||||
|
+ if (asprintf(&path, "/proc/fs/nfsd/clients/%lu/info", key->num) < 0)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ f = fopen(path, "r");
|
||||||
|
+ if (!f) {
|
||||||
|
+ free(path);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ if (key->wid < 0)
|
||||||
|
+ key->wid = inotify_add_watch(clients_fd, path, IN_MODIFY);
|
||||||
|
+
|
||||||
|
+ while (fgets(buf, sizeof(buf), f)) {
|
||||||
|
+ if (strncmp(buf, "clientid: ", 10) == 0) {
|
||||||
|
+ free(key->clientid);
|
||||||
|
+ key->clientid = dup_line(buf+10);
|
||||||
|
+ }
|
||||||
|
+ if (strncmp(buf, "address: ", 9) == 0) {
|
||||||
|
+ free(key->addr);
|
||||||
|
+ key->addr = dup_line(buf+9);
|
||||||
|
+ }
|
||||||
|
+ if (strncmp(buf, "minor version: ", 15) == 0)
|
||||||
|
+ key->vers = atoi(buf+15);
|
||||||
|
+ if (strncmp(buf, "status: ", 8) == 0 &&
|
||||||
|
+ strstr(buf, " unconfirmed") != NULL) {
|
||||||
|
+ key->unconfirmed = 1;
|
||||||
|
+ have_unconfirmed = 1;
|
||||||
|
+ }
|
||||||
|
+ if (strncmp(buf, "status: ", 8) == 0 &&
|
||||||
|
+ strstr(buf, " confirmed") != NULL)
|
||||||
|
+ key->unconfirmed = 0;
|
||||||
|
+ }
|
||||||
|
+ fclose(f);
|
||||||
|
+ free(path);
|
||||||
|
+
|
||||||
|
+ if (was_unconfirmed && !key->unconfirmed)
|
||||||
|
+ xlog(L_NOTICE, "v4.%d client attached: %s from %s",
|
||||||
|
+ key->vers, key->clientid ?: "-none-",
|
||||||
|
+ key->addr ?: "-none-");
|
||||||
|
+ if (!key->unconfirmed && key->wid >= 0) {
|
||||||
|
+ inotify_rm_watch(clients_fd, key->wid);
|
||||||
|
+ key->wid = -1;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void add_id(int id)
|
||||||
|
+{
|
||||||
|
+ struct ent **ent;
|
||||||
|
+ struct ent *key;
|
||||||
|
+
|
||||||
|
+ key = calloc(1, sizeof(*key));
|
||||||
|
+ if (!key) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ key->num = id;
|
||||||
|
+ key->wid = -1;
|
||||||
|
+
|
||||||
|
+ ent = tsearch(key, &tree_root, ent_cmp);
|
||||||
|
+
|
||||||
|
+ if (!ent || *ent != key)
|
||||||
|
+ /* Already existed, or insertion failed */
|
||||||
|
+ free_ent(key);
|
||||||
|
+ else
|
||||||
|
+ read_info(key);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void del_id(unsigned long id)
|
||||||
|
+{
|
||||||
|
+ struct ent key = {.num = id};
|
||||||
|
+ struct ent **e, *ent;
|
||||||
|
+
|
||||||
|
+ e = tfind(&key, &tree_root, ent_cmp);
|
||||||
|
+ if (!e || !*e)
|
||||||
|
+ return;
|
||||||
|
+ ent = *e;
|
||||||
|
+ tdelete(ent, &tree_root, ent_cmp);
|
||||||
|
+ if (!ent->unconfirmed)
|
||||||
|
+ xlog(L_NOTICE, "v4.%d client detached: %s from %s",
|
||||||
|
+ ent->vers, ent->clientid, ent->addr);
|
||||||
|
+ if (ent->wid >= 0)
|
||||||
|
+ inotify_rm_watch(clients_fd, ent->wid);
|
||||||
|
+ free_ent(ent);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void check_id(unsigned long id)
|
||||||
|
+{
|
||||||
|
+ struct ent key = {.num = id};
|
||||||
|
+ struct ent **e, *ent;
|
||||||
|
+
|
||||||
|
+ e = tfind(&key, &tree_root, ent_cmp);
|
||||||
|
+ if (!e || !*e)
|
||||||
|
+ return;
|
||||||
|
+ ent = *e;
|
||||||
|
+ if (ent->unconfirmed)
|
||||||
|
+ read_info(ent);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int v4clients_process(fd_set *fdset)
|
||||||
|
+{
|
||||||
|
+ char buf[4096] __attribute__((aligned(__alignof__(struct inotify_event))));
|
||||||
|
+ const struct inotify_event *ev;
|
||||||
|
+ ssize_t len;
|
||||||
|
+ char *ptr;
|
||||||
|
+
|
||||||
|
+ if (clients_fd < 0 ||
|
||||||
|
+ !FD_ISSET(clients_fd, fdset))
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ while ((len = read(clients_fd, buf, sizeof(buf))) > 0) {
|
||||||
|
+ for (ptr = buf; ptr < buf + len;
|
||||||
|
+ ptr += sizeof(struct inotify_event) + ev->len) {
|
||||||
|
+ int id;
|
||||||
|
+ ev = (const struct inotify_event *)ptr;
|
||||||
|
+
|
||||||
|
+ id = atoi(ev->name);
|
||||||
|
+ if (id <= 0)
|
||||||
|
+ continue;
|
||||||
|
+ if (ev->mask & IN_CREATE)
|
||||||
|
+ add_id(id);
|
||||||
|
+ if (ev->mask & IN_DELETE)
|
||||||
|
+ del_id(id);
|
||||||
|
+ if (ev->mask & IN_MODIFY)
|
||||||
|
+ check_id(id);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
diff --git a/utils/mountd/v4root.c b/support/export/v4root.c
|
||||||
|
similarity index 99%
|
||||||
|
rename from utils/mountd/v4root.c
|
||||||
|
rename to support/export/v4root.c
|
||||||
|
index 8ec33fb0..4d33117f 100644
|
||||||
|
--- a/utils/mountd/v4root.c
|
||||||
|
+++ b/support/export/v4root.c
|
||||||
|
@@ -47,7 +47,7 @@ static nfs_export pseudo_root = {
|
||||||
|
.e_nsqgids = 0,
|
||||||
|
.e_fsid = 0,
|
||||||
|
.e_mountpoint = NULL,
|
||||||
|
- .e_ttl = DEFAULT_TTL,
|
||||||
|
+ .e_ttl = 0,
|
||||||
|
},
|
||||||
|
.m_exported = 0,
|
||||||
|
.m_xtabent = 1,
|
||||||
|
@@ -86,6 +86,7 @@ v4root_create(char *path, nfs_export *export)
|
||||||
|
struct exportent *curexp = &export->m_export;
|
||||||
|
|
||||||
|
dupexportent(&eep, &pseudo_root.m_export);
|
||||||
|
+ eep.e_ttl = default_ttl;
|
||||||
|
eep.e_hostname = curexp->e_hostname;
|
||||||
|
strncpy(eep.e_path, path, sizeof(eep.e_path)-1);
|
||||||
|
if (strcmp(path, "/") != 0)
|
||||||
|
diff --git a/support/include/exportfs.h b/support/include/exportfs.h
|
||||||
|
index 4e0d9d13..bfae1957 100644
|
||||||
|
--- a/support/include/exportfs.h
|
||||||
|
+++ b/support/include/exportfs.h
|
||||||
|
@@ -105,7 +105,8 @@ typedef struct mexport {
|
||||||
|
} nfs_export;
|
||||||
|
|
||||||
|
#define HASH_TABLE_SIZE 1021
|
||||||
|
-#define DEFAULT_TTL (30 * 60)
|
||||||
|
+
|
||||||
|
+extern int default_ttl;
|
||||||
|
|
||||||
|
typedef struct _exp_hash_entry {
|
||||||
|
nfs_export * p_first;
|
||||||
|
diff --git a/support/nfs/exports.c b/support/nfs/exports.c
|
||||||
|
index a7582cae..4dd2e5d3 100644
|
||||||
|
--- a/support/nfs/exports.c
|
||||||
|
+++ b/support/nfs/exports.c
|
||||||
|
@@ -47,6 +47,8 @@ struct flav_info flav_map[] = {
|
||||||
|
|
||||||
|
const int flav_map_size = sizeof(flav_map)/sizeof(flav_map[0]);
|
||||||
|
|
||||||
|
+int default_ttl = 30 * 60;
|
||||||
|
+
|
||||||
|
static char *efname = NULL;
|
||||||
|
static XFILE *efp = NULL;
|
||||||
|
static int first;
|
||||||
|
@@ -100,7 +102,7 @@ static void init_exportent (struct exportent *ee, int fromkernel)
|
||||||
|
ee->e_nsquids = 0;
|
||||||
|
ee->e_nsqgids = 0;
|
||||||
|
ee->e_uuid = NULL;
|
||||||
|
- ee->e_ttl = DEFAULT_TTL;
|
||||||
|
+ ee->e_ttl = default_ttl;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct exportent *
|
||||||
|
diff --git a/systemd/nfs.conf.man b/systemd/nfs.conf.man
|
||||||
|
index 498d93a9..aa4630bb 100644
|
||||||
|
--- a/systemd/nfs.conf.man
|
||||||
|
+++ b/systemd/nfs.conf.man
|
||||||
|
@@ -157,6 +157,8 @@ Recognized values:
|
||||||
|
.BR port ,
|
||||||
|
.BR threads ,
|
||||||
|
.BR reverse-lookup ,
|
||||||
|
+.BR cache-use-upaddr ,
|
||||||
|
+.BR ttl ,
|
||||||
|
.BR state-directory-path ,
|
||||||
|
.BR ha-callout .
|
||||||
|
|
||||||
|
@@ -166,6 +168,14 @@ section, are used to configure mountd. See
|
||||||
|
.BR rpc.mountd (8)
|
||||||
|
for details.
|
||||||
|
|
||||||
|
+Note that setting
|
||||||
|
+.B "\[dq]debug = auth\[dq]"
|
||||||
|
+for
|
||||||
|
+.B mountd
|
||||||
|
+is equivalent to providing the
|
||||||
|
+.B \-\-log\-auth
|
||||||
|
+option.
|
||||||
|
+
|
||||||
|
The
|
||||||
|
.B state-directory-path
|
||||||
|
value in the
|
||||||
|
diff --git a/utils/mountd/Makefile.am b/utils/mountd/Makefile.am
|
||||||
|
index 73eeb3f3..c41f06de 100644
|
||||||
|
--- a/utils/mountd/Makefile.am
|
||||||
|
+++ b/utils/mountd/Makefile.am
|
||||||
|
@@ -13,8 +13,8 @@ KPREFIX = @kprefix@
|
||||||
|
sbin_PROGRAMS = mountd
|
||||||
|
|
||||||
|
noinst_HEADERS = fsloc.h
|
||||||
|
-mountd_SOURCES = mountd.c mount_dispatch.c auth.c rmtab.c cache.c \
|
||||||
|
- svc_run.c fsloc.c v4root.c mountd.h
|
||||||
|
+mountd_SOURCES = mountd.c mount_dispatch.c rmtab.c \
|
||||||
|
+ svc_run.c fsloc.c mountd.h
|
||||||
|
mountd_LDADD = ../../support/export/libexport.a \
|
||||||
|
../../support/nfs/libnfs.la \
|
||||||
|
../../support/misc/libmisc.a \
|
||||||
|
diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c
|
||||||
|
index 0b891121..2b342377 100644
|
||||||
|
--- a/utils/mountd/mountd.c
|
||||||
|
+++ b/utils/mountd/mountd.c
|
||||||
|
@@ -30,6 +30,7 @@
|
||||||
|
#include "rpcmisc.h"
|
||||||
|
#include "pseudoflavors.h"
|
||||||
|
#include "nfslib.h"
|
||||||
|
+#include "export.h"
|
||||||
|
|
||||||
|
extern void my_svc_run(void);
|
||||||
|
|
||||||
|
@@ -73,8 +74,12 @@ static struct option longopts[] =
|
||||||
|
{ "reverse-lookup", 0, 0, 'r' },
|
||||||
|
{ "manage-gids", 0, 0, 'g' },
|
||||||
|
{ "no-udp", 0, 0, 'u' },
|
||||||
|
+ { "log-auth", 0, 0, 'l'},
|
||||||
|
+ { "cache-use-ipaddr", 0, 0, 'i'},
|
||||||
|
+ { "ttl", 1, 0, 'T'},
|
||||||
|
{ NULL, 0, 0, 0 }
|
||||||
|
};
|
||||||
|
+static char shortopts[] = "o:nFd:p:P:hH:N:V:vurs:t:gliT:";
|
||||||
|
|
||||||
|
#define NFSVERSBIT(vers) (0x1 << (vers - 1))
|
||||||
|
#define NFSVERSBIT_ALL (NFSVERSBIT(2) | NFSVERSBIT(3) | NFSVERSBIT(4))
|
||||||
|
@@ -669,6 +674,7 @@ main(int argc, char **argv)
|
||||||
|
int port = 0;
|
||||||
|
int descriptors = 0;
|
||||||
|
int c;
|
||||||
|
+ int ttl;
|
||||||
|
int vers;
|
||||||
|
struct sigaction sa;
|
||||||
|
struct rlimit rlim;
|
||||||
|
@@ -687,6 +693,8 @@ main(int argc, char **argv)
|
||||||
|
num_threads = conf_get_num("mountd", "threads", num_threads);
|
||||||
|
reverse_resolve = conf_get_bool("mountd", "reverse-lookup", reverse_resolve);
|
||||||
|
ha_callout_prog = conf_get_str("mountd", "ha-callout");
|
||||||
|
+ if (conf_get_bool("mountd", "cache-use-ipaddr", 0))
|
||||||
|
+ use_ipaddr = 2;
|
||||||
|
|
||||||
|
s = conf_get_str("mountd", "state-directory-path");
|
||||||
|
if (s && !state_setup_basedir(argv[0], s))
|
||||||
|
@@ -710,10 +718,13 @@ main(int argc, char **argv)
|
||||||
|
NFSCTL_VERUNSET(nfs_version, vers);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ ttl = conf_get_num("mountd", "ttl", default_ttl);
|
||||||
|
+ if (ttl > 0)
|
||||||
|
+ default_ttl = ttl;
|
||||||
|
|
||||||
|
/* Parse the command line options and arguments. */
|
||||||
|
opterr = 0;
|
||||||
|
- while ((c = getopt_long(argc, argv, "o:nFd:p:P:hH:N:V:vurs:t:g", longopts, NULL)) != EOF)
|
||||||
|
+ while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != EOF)
|
||||||
|
switch (c) {
|
||||||
|
case 'g':
|
||||||
|
manage_gids = 1;
|
||||||
|
@@ -784,6 +795,21 @@ main(int argc, char **argv)
|
||||||
|
case 'u':
|
||||||
|
NFSCTL_UDPUNSET(_rpcprotobits);
|
||||||
|
break;
|
||||||
|
+ case 'l':
|
||||||
|
+ xlog_sconfig("auth", 1);
|
||||||
|
+ break;
|
||||||
|
+ case 'i':
|
||||||
|
+ use_ipaddr = 2;
|
||||||
|
+ break;
|
||||||
|
+ case 'T':
|
||||||
|
+ ttl = atoi(optarg);
|
||||||
|
+ if (ttl <= 0) {
|
||||||
|
+ fprintf(stderr, "%s: bad ttl number of seconds: %s\n",
|
||||||
|
+ argv[0], optarg);
|
||||||
|
+ usage(argv[0], 1);
|
||||||
|
+ }
|
||||||
|
+ default_ttl = ttl;
|
||||||
|
+ break;
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
@@ -888,6 +914,8 @@ main(int argc, char **argv)
|
||||||
|
if (num_threads > 1)
|
||||||
|
fork_workers();
|
||||||
|
|
||||||
|
+ v4clients_init();
|
||||||
|
+
|
||||||
|
xlog(L_NOTICE, "Version " VERSION " starting");
|
||||||
|
my_svc_run();
|
||||||
|
|
||||||
|
@@ -903,6 +931,7 @@ usage(const char *prog, int n)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Usage: %s [-F|--foreground] [-h|--help] [-v|--version] [-d kind|--debug kind]\n"
|
||||||
|
+" [-l|--log-auth] [-i|--cache-use-ipaddr] [-T|--ttl ttl]\n"
|
||||||
|
" [-o num|--descriptors num]\n"
|
||||||
|
" [-p|--port port] [-V version|--nfs-version version]\n"
|
||||||
|
" [-N version|--no-nfs-version version] [-n|--no-tcp]\n"
|
||||||
|
diff --git a/utils/mountd/mountd.h b/utils/mountd/mountd.h
|
||||||
|
index f058f01d..d3077531 100644
|
||||||
|
--- a/utils/mountd/mountd.h
|
||||||
|
+++ b/utils/mountd/mountd.h
|
||||||
|
@@ -60,9 +60,4 @@ bool ipaddr_client_matches(nfs_export *exp, struct addrinfo *ai);
|
||||||
|
bool namelist_client_matches(nfs_export *exp, char *dom);
|
||||||
|
bool client_matches(nfs_export *exp, char *dom, struct addrinfo *ai);
|
||||||
|
|
||||||
|
-static inline bool is_ipaddr_client(char *dom)
|
||||||
|
-{
|
||||||
|
- return dom[0] == '$';
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
#endif /* MOUNTD_H */
|
||||||
|
diff --git a/utils/mountd/mountd.man b/utils/mountd/mountd.man
|
||||||
|
index 8a7943f8..2a91e193 100644
|
||||||
|
--- a/utils/mountd/mountd.man
|
||||||
|
+++ b/utils/mountd/mountd.man
|
||||||
|
@@ -13,24 +13,24 @@ The
|
||||||
|
.B rpc.mountd
|
||||||
|
daemon implements the server side of the NFS MOUNT protocol,
|
||||||
|
an NFS side protocol used by NFS version 2 [RFC1094] and NFS version 3 [RFC1813].
|
||||||
|
+It also responds to requests from the Linux kernel to authenticate
|
||||||
|
+clients and provides details of access permissions.
|
||||||
|
.PP
|
||||||
|
-An NFS server maintains a table of local physical file systems
|
||||||
|
-that are accessible to NFS clients.
|
||||||
|
-Each file system in this table is referred to as an
|
||||||
|
-.IR "exported file system" ,
|
||||||
|
-or
|
||||||
|
-.IR export ,
|
||||||
|
-for short.
|
||||||
|
-.PP
|
||||||
|
-Each file system in the export table has an access control list.
|
||||||
|
-.B rpc.mountd
|
||||||
|
-uses these access control lists to determine
|
||||||
|
-whether an NFS client is permitted to access a given file system.
|
||||||
|
-For details on how to manage your NFS server's export table, see the
|
||||||
|
-.BR exports (5)
|
||||||
|
-and
|
||||||
|
-.BR exportfs (8)
|
||||||
|
-man pages.
|
||||||
|
+The NFS server
|
||||||
|
+.RI ( nfsd )
|
||||||
|
+maintains a cache of authentication and authorization information which
|
||||||
|
+is used to identify the source of each request, and then what access
|
||||||
|
+permissions that source has to any local filesystem. When required
|
||||||
|
+information is not found in the cache, the server sends a request to
|
||||||
|
+.B mountd
|
||||||
|
+to fill in the missing information. Mountd uses a table of information
|
||||||
|
+stored in
|
||||||
|
+.B /var/lib/nfs/etab
|
||||||
|
+and maintained by
|
||||||
|
+.BR exportfs (8),
|
||||||
|
+possibly based on the contents of
|
||||||
|
+.BR exports (5),
|
||||||
|
+to respond to each request.
|
||||||
|
.SS Mounting exported NFS File Systems
|
||||||
|
The NFS MOUNT protocol has several procedures.
|
||||||
|
The most important of these are
|
||||||
|
@@ -78,11 +78,69 @@ A client may continue accessing an export even after invoking UMNT.
|
||||||
|
If the client reboots without sending a UMNT request, stale entries
|
||||||
|
remain for that client in
|
||||||
|
.IR /var/lib/nfs/rmtab .
|
||||||
|
+.SS Mounting File Systems with NFSv4
|
||||||
|
+Version 4 (and later) of NFS does not use a separate NFS MOUNT
|
||||||
|
+protocol. Instead mounting is performed using regular NFS requests
|
||||||
|
+handled by the NFS server in the Linux kernel
|
||||||
|
+.RI ( nfsd ).
|
||||||
|
+Consequently
|
||||||
|
+.I /var/lib/nfs/rmtab
|
||||||
|
+is not updated to reflect any NFSv4 activity.
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
.B \-d kind " or " \-\-debug kind
|
||||||
|
Turn on debugging. Valid kinds are: all, auth, call, general and parse.
|
||||||
|
.TP
|
||||||
|
+.BR \-l " or " \-\-log\-auth
|
||||||
|
+Enable logging of responses to authentication and access requests from
|
||||||
|
+nfsd. Each response is then cached by the kernel for 30 minutes (or as set by
|
||||||
|
+.B \-\-ttl
|
||||||
|
+below), and will be refreshed after 15 minutes (half the ttl time) if
|
||||||
|
+the relevant client remains active.
|
||||||
|
+Note that
|
||||||
|
+.B -l
|
||||||
|
+is equivalent to
|
||||||
|
+.B "-d auth"
|
||||||
|
+and so can be enabled in
|
||||||
|
+.B /etc/nfs.conf
|
||||||
|
+with
|
||||||
|
+.B "\[dq]debug = auth\[dq]"
|
||||||
|
+in the
|
||||||
|
+.B "[mountd]"
|
||||||
|
+section.
|
||||||
|
+.IP
|
||||||
|
+.B rpc.mountd
|
||||||
|
+will always log authentication responses to MOUNT requests when NFSv3 is
|
||||||
|
+used, but to get similar logs for NFSv4, this option is required.
|
||||||
|
+.TP
|
||||||
|
+.BR \-i " or " \-\-cache\-use\-ipaddr
|
||||||
|
+Normally each client IP address is matched against each host identifier
|
||||||
|
+(name, wildcard, netgroup etc) found in
|
||||||
|
+.B /etc/exports
|
||||||
|
+and a combined identity is formed from all matching identifiers.
|
||||||
|
+Often many clients will map to the same combined identity so performing
|
||||||
|
+this mapping reduces the number of distinct access details that the
|
||||||
|
+kernel needs to store.
|
||||||
|
+Specifying the
|
||||||
|
+.B \-i
|
||||||
|
+option suppresses this mapping so that access to each filesystem is
|
||||||
|
+requested and cached separately for each client IP address. Doing this
|
||||||
|
+can increase the burden of updating the cache slightly, but can make the
|
||||||
|
+log messages produced by the
|
||||||
|
+.B -l
|
||||||
|
+option easier to read.
|
||||||
|
+.TP
|
||||||
|
+.B \-T " or " \-\-ttl
|
||||||
|
+Provide a time-to-live (TTL) for cached information given to the kernel.
|
||||||
|
+The kernel will normally request an update if the information is needed
|
||||||
|
+after half of this time has expired. Increasing the provided number,
|
||||||
|
+which is in seconds, reduces the rate of cache update requests, and this
|
||||||
|
+is particularly noticeable when these requests are logged with
|
||||||
|
+.BR \-l .
|
||||||
|
+However increasing also means that changes to hostname to address
|
||||||
|
+mappings can take longer to be noticed.
|
||||||
|
+The default TTL is 1800 (30 minutes).
|
||||||
|
+.TP
|
||||||
|
.B \-F " or " \-\-foreground
|
||||||
|
Run in foreground (do not daemonize)
|
||||||
|
.TP
|
||||||
|
@@ -213,9 +271,11 @@ Values recognized in the
|
||||||
|
.B [mountd]
|
||||||
|
section include
|
||||||
|
.BR manage-gids ,
|
||||||
|
+.BR cache\-use\-ipaddr ,
|
||||||
|
.BR descriptors ,
|
||||||
|
.BR port ,
|
||||||
|
.BR threads ,
|
||||||
|
+.BR ttl ,
|
||||||
|
.BR reverse-lookup ", and"
|
||||||
|
.BR state-directory-path ,
|
||||||
|
.B ha-callout
|
||||||
|
@@ -265,5 +325,9 @@ table of clients accessing server's exports
|
||||||
|
RFC 1094 - "NFS: Network File System Protocol Specification"
|
||||||
|
.br
|
||||||
|
RFC 1813 - "NFS Version 3 Protocol Specification"
|
||||||
|
+.br
|
||||||
|
+RFC 7530 - "Network File System (NFS) Version 4 Protocol"
|
||||||
|
+.br
|
||||||
|
+RFC 8881 - "Network File System (NFS) Version 4 Minor Version 1 Protocol"
|
||||||
|
.SH AUTHOR
|
||||||
|
Olaf Kirch, H. J. Lu, G. Allan Morris III, and a host of others.
|
||||||
|
diff --git a/utils/mountd/svc_run.c b/utils/mountd/svc_run.c
|
||||||
|
index 41b96d7f..167b9757 100644
|
||||||
|
--- a/utils/mountd/svc_run.c
|
||||||
|
+++ b/utils/mountd/svc_run.c
|
||||||
|
@@ -56,10 +56,9 @@
|
||||||
|
#ifdef HAVE_LIBTIRPC
|
||||||
|
#include <rpc/rpc_com.h>
|
||||||
|
#endif
|
||||||
|
+#include "export.h"
|
||||||
|
|
||||||
|
void my_svc_run(void);
|
||||||
|
-void cache_set_fds(fd_set *fdset);
|
||||||
|
-int cache_process_req(fd_set *readfds);
|
||||||
|
|
||||||
|
#if defined(__GLIBC__) && LONG_MAX != INT_MAX
|
||||||
|
/* bug in glibc 2.3.6 and earlier, we need
|
||||||
|
@@ -101,6 +100,7 @@ my_svc_run(void)
|
||||||
|
|
||||||
|
readfds = svc_fdset;
|
||||||
|
cache_set_fds(&readfds);
|
||||||
|
+ v4clients_set_fds(&readfds);
|
||||||
|
|
||||||
|
selret = select(FD_SETSIZE, &readfds,
|
||||||
|
(void *) 0, (void *) 0, (struct timeval *) 0);
|
||||||
|
@@ -116,6 +116,7 @@ my_svc_run(void)
|
||||||
|
|
||||||
|
default:
|
||||||
|
selret -= cache_process_req(&readfds);
|
||||||
|
+ selret -= v4clients_process(&readfds);
|
||||||
|
if (selret)
|
||||||
|
svc_getreqset(&readfds);
|
||||||
|
}
|
24
SOURCES/nfs-utils-2.3.3-mountd-v4clnts.patch
Normal file
24
SOURCES/nfs-utils-2.3.3-mountd-v4clnts.patch
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
diff -up nfs-utils-2.3.3/support/export/v4clients.c.orig nfs-utils-2.3.3/support/export/v4clients.c
|
||||||
|
--- nfs-utils-2.3.3/support/export/v4clients.c.orig 2022-09-26 11:36:22.803929066 -0400
|
||||||
|
+++ nfs-utils-2.3.3/support/export/v4clients.c 2022-09-26 11:38:38.221187835 -0400
|
||||||
|
@@ -8,6 +8,7 @@
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/inotify.h>
|
||||||
|
+#include <sys/stat.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "export.h"
|
||||||
|
|
||||||
|
@@ -23,6 +24,12 @@ static int clients_fd = -1;
|
||||||
|
|
||||||
|
void v4clients_init(void)
|
||||||
|
{
|
||||||
|
+ struct stat sb;
|
||||||
|
+
|
||||||
|
+ if (!stat("/proc/fs/nfsd/clients", &sb) == 0 ||
|
||||||
|
+ !S_ISDIR(sb.st_mode))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
if (clients_fd >= 0)
|
||||||
|
return;
|
||||||
|
clients_fd = inotify_init1(IN_NONBLOCK);
|
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:
|
40
SOURCES/nfs-utils-2.3.3-nconnect-manpage.patch
Normal file
40
SOURCES/nfs-utils-2.3.3-nconnect-manpage.patch
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
commit 3ff6fad27d2cd0772a40ddb65694ce04f3da83bc
|
||||||
|
Author: Trond Myklebust <trond.myklebust@hammerspace.com>
|
||||||
|
Date: Wed Jan 29 10:42:03 2020 -0500
|
||||||
|
|
||||||
|
manpage: Add a description of the 'nconnect' mount option
|
||||||
|
|
||||||
|
Add a description of the 'nconnect' mount option on the 'nfs' generic
|
||||||
|
manpage.
|
||||||
|
|
||||||
|
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
|
||||||
|
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/utils/mount/nfs.man b/utils/mount/nfs.man
|
||||||
|
index 6ba9cef..84462cd 100644
|
||||||
|
--- a/utils/mount/nfs.man
|
||||||
|
+++ b/utils/mount/nfs.man
|
||||||
|
@@ -369,6 +369,23 @@ using an automounter (refer to
|
||||||
|
.BR automount (8)
|
||||||
|
for details).
|
||||||
|
.TP 1.5i
|
||||||
|
+.BR nconnect= n
|
||||||
|
+When using a connection oriented protocol such as TCP, it may
|
||||||
|
+sometimes be advantageous to set up multiple connections between
|
||||||
|
+the client and server. For instance, if your clients and/or servers
|
||||||
|
+are equipped with multiple network interface cards (NICs), using multiple
|
||||||
|
+connections to spread the load may improve overall performance.
|
||||||
|
+In such cases, the
|
||||||
|
+.BR nconnect
|
||||||
|
+option allows the user to specify the number of connections
|
||||||
|
+that should be established between the client and server up to
|
||||||
|
+a limit of 16.
|
||||||
|
+.IP
|
||||||
|
+Note that the
|
||||||
|
+.BR nconnect
|
||||||
|
+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
|
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
|
||||||
|
|
481
SOURCES/nfs-utils-2.3.3-nfsclnts-cmd.patch
Normal file
481
SOURCES/nfs-utils-2.3.3-nfsclnts-cmd.patch
Normal file
@ -0,0 +1,481 @@
|
|||||||
|
diff -up nfs-utils-2.3.3/configure.ac.orig nfs-utils-2.3.3/configure.ac
|
||||||
|
--- nfs-utils-2.3.3/configure.ac.orig 2020-06-09 10:58:50.178258035 -0400
|
||||||
|
+++ nfs-utils-2.3.3/configure.ac 2020-06-09 11:02:04.203102954 -0400
|
||||||
|
@@ -639,6 +639,7 @@ AC_CONFIG_FILES([
|
||||||
|
tools/rpcgen/Makefile
|
||||||
|
tools/mountstats/Makefile
|
||||||
|
tools/nfs-iostat/Makefile
|
||||||
|
+ tools/nfsdclnts/Makefile
|
||||||
|
tools/nfsconf/Makefile
|
||||||
|
tools/nfsdclddb/Makefile
|
||||||
|
utils/Makefile
|
||||||
|
diff -up nfs-utils-2.3.3/tools/Makefile.am.orig nfs-utils-2.3.3/tools/Makefile.am
|
||||||
|
--- nfs-utils-2.3.3/tools/Makefile.am.orig 2020-06-09 10:58:50.178258035 -0400
|
||||||
|
+++ nfs-utils-2.3.3/tools/Makefile.am 2020-06-09 11:02:04.203102954 -0400
|
||||||
|
@@ -12,6 +12,6 @@ if CONFIG_NFSDCLD
|
||||||
|
OPTDIRS += nfsdclddb
|
||||||
|
endif
|
||||||
|
|
||||||
|
-SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat $(OPTDIRS)
|
||||||
|
+SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat nfsdclnts $(OPTDIRS)
|
||||||
|
|
||||||
|
MAINTAINERCLEANFILES = Makefile.in
|
||||||
|
diff -up nfs-utils-2.3.3/tools/nfsdclnts/Makefile.am.orig nfs-utils-2.3.3/tools/nfsdclnts/Makefile.am
|
||||||
|
--- nfs-utils-2.3.3/tools/nfsdclnts/Makefile.am.orig 2020-06-09 11:02:04.203102954 -0400
|
||||||
|
+++ nfs-utils-2.3.3/tools/nfsdclnts/Makefile.am 2020-06-09 11:02:04.203102954 -0400
|
||||||
|
@@ -0,0 +1,13 @@
|
||||||
|
+## Process this file with automake to produce Makefile.in
|
||||||
|
+PYTHON_FILES = nfsdclnts.py
|
||||||
|
+
|
||||||
|
+man8_MANS = nfsdclnts.man
|
||||||
|
+
|
||||||
|
+EXTRA_DIST = $(man8_MANS) $(PYTHON_FILES)
|
||||||
|
+
|
||||||
|
+all-local: $(PYTHON_FILES)
|
||||||
|
+
|
||||||
|
+install-data-hook:
|
||||||
|
+ $(INSTALL) -m 755 nfsdclnts.py $(DESTDIR)$(sbindir)/nfsdclnts
|
||||||
|
+
|
||||||
|
+MAINTAINERCLEANFILES=Makefile.in
|
||||||
|
diff -up nfs-utils-2.3.3/tools/nfsdclnts/nfsdclnts.man.orig nfs-utils-2.3.3/tools/nfsdclnts/nfsdclnts.man
|
||||||
|
--- nfs-utils-2.3.3/tools/nfsdclnts/nfsdclnts.man.orig 2020-06-09 11:02:04.203102954 -0400
|
||||||
|
+++ nfs-utils-2.3.3/tools/nfsdclnts/nfsdclnts.man 2020-06-09 11:02:04.203102954 -0400
|
||||||
|
@@ -0,0 +1,180 @@
|
||||||
|
+.\"
|
||||||
|
+.\" nfsdclnts(8)
|
||||||
|
+.\"
|
||||||
|
+.TH "NFSDCLTS" "8" "2020-05-09" "nfsdclnts" "nfsdclnts"
|
||||||
|
+.ie \n(.g .ds Aq \(aq
|
||||||
|
+.el .ds Aq '
|
||||||
|
+.ss \n[.ss] 0
|
||||||
|
+.nh
|
||||||
|
+.ad l
|
||||||
|
+.de URL
|
||||||
|
+\fI\\$2\fP <\\$1>\\$3
|
||||||
|
+..
|
||||||
|
+.als MTO URL
|
||||||
|
+.if \n[.g] \{\
|
||||||
|
+. mso www.tmac
|
||||||
|
+. am URL
|
||||||
|
+. ad l
|
||||||
|
+. .
|
||||||
|
+. am MTO
|
||||||
|
+. ad l
|
||||||
|
+. .
|
||||||
|
+. LINKSTYLE blue R < >
|
||||||
|
+.\}
|
||||||
|
+.SH "NAME"
|
||||||
|
+nfsdclnts \- print various nfs client information for knfsd server.
|
||||||
|
+.SH "SYNOPSIS"
|
||||||
|
+.sp
|
||||||
|
+\fBnfsdclnts\fP [\fI\-h\fP] [\fI\-t type\fP] [\fI\-\-clientinfo\fP] [\fI\-\-hostname\fP] [\fI\-q\fP]
|
||||||
|
+.SH "DESCRIPTION"
|
||||||
|
+.sp
|
||||||
|
+The nfsdclnts(8) command parses the content present in /proc/fs/nfsd/clients/ directories. nfsdclnts(8) displays files which are open, locked, delegated by the nfs\-client. It also prints useful client information such as hostname, clientID, NFS version mounted by the nfs\-client.
|
||||||
|
+.SH "OPTIONS"
|
||||||
|
+.sp
|
||||||
|
+\fB\-t, \-\-type\fP=TYPE
|
||||||
|
+.RS 4
|
||||||
|
+Specify the type of file to be displayed. Takes only one TYPE at a time.
|
||||||
|
+.sp
|
||||||
|
+\fIopen\fP, \fIlock\fP, \fIdeleg\fP, \fIlayout\fP, or \fIall\fP
|
||||||
|
+.sp
|
||||||
|
+open: displays the open files by nfs\-client(s).
|
||||||
|
+.sp
|
||||||
|
+lock: displays the files locked by nfs\-client(s).
|
||||||
|
+.sp
|
||||||
|
+layout: displays the files for which layout is given.
|
||||||
|
+.sp
|
||||||
|
+deleg: displays delegated files information and delegation type.
|
||||||
|
+.sp
|
||||||
|
+all: prints all the above type.
|
||||||
|
+.RE
|
||||||
|
+.sp
|
||||||
|
+\fB\-\-clientinfo\fP
|
||||||
|
+.RS 4
|
||||||
|
+displays various nfs\-client info fields such as version of nfs mounted at nfs\-client and clientID.
|
||||||
|
+.RE
|
||||||
|
+.sp
|
||||||
|
+\fB\-\-hostname\fP
|
||||||
|
+.RS 4
|
||||||
|
+Print hostname of nfs\-client instead of ip-address.
|
||||||
|
+.RE
|
||||||
|
+.sp
|
||||||
|
+\fB\-q, \-\-quiet\fP
|
||||||
|
+.RS 4
|
||||||
|
+Hide the header information.
|
||||||
|
+.RE
|
||||||
|
+.sp
|
||||||
|
+\fB\-v, \-\-verbose\fP
|
||||||
|
+.RS 4
|
||||||
|
+Verbose operation, show debug messages.
|
||||||
|
+.RE
|
||||||
|
+.sp
|
||||||
|
+\fB\-f, \-\-file\fP
|
||||||
|
+.RS 4
|
||||||
|
+Instead of processing all client directories under /proc/fs/nfsd/clients, one can provide a specific
|
||||||
|
+states file to process. One should make sure that info file resides in the same directory as states file.
|
||||||
|
+If the info file is not valid or present the fields would be marked as "N/A".
|
||||||
|
+.RE
|
||||||
|
+.sp
|
||||||
|
+\fB\-h, \-\-help\fP
|
||||||
|
+.RS 4
|
||||||
|
+Print help explaining the command line options.
|
||||||
|
+.SH "EXAMPLES"
|
||||||
|
+.sp
|
||||||
|
+\fBnfsdclnts \-\-type open\fP
|
||||||
|
+.RS 4
|
||||||
|
+List all files with open type only.
|
||||||
|
+.RE
|
||||||
|
+.sp
|
||||||
|
+.if n .RS 4
|
||||||
|
+.nf
|
||||||
|
+Inode number | Type | Access | Deny | ip address | Filename
|
||||||
|
+33823232 | open | r\- | \-\- | [::1]:757 | testfile
|
||||||
|
+.fi
|
||||||
|
+.if n .RE
|
||||||
|
+.sp
|
||||||
|
+\fBnfsdclnts \-\-type deleg\fP
|
||||||
|
+.RS 4
|
||||||
|
+List all files with deleg type only.
|
||||||
|
+.RE
|
||||||
|
+.sp
|
||||||
|
+.if n .RS 4
|
||||||
|
+.nf
|
||||||
|
+Inode number | Type | Access | ip address | Filename
|
||||||
|
+33823232 | deleg | r | [::1]:757 | testfile
|
||||||
|
+.fi
|
||||||
|
+.if n .RE
|
||||||
|
+.sp
|
||||||
|
+\fBnfsdclnts \-\-hostname\fP
|
||||||
|
+.RS 4
|
||||||
|
+Print hostname instead of ip\-address.
|
||||||
|
+.RE
|
||||||
|
+.sp
|
||||||
|
+.if n .RS 4
|
||||||
|
+.nf
|
||||||
|
+Inode number | Type | Access | Deny | Hostname | Filename
|
||||||
|
+33823232 | open | r\- | \-\- | nfs\-server | testfile
|
||||||
|
+33823232 | deleg | r | | nfs\-server | testfile
|
||||||
|
+.fi
|
||||||
|
+.if n .RE
|
||||||
|
+.sp
|
||||||
|
+\fBnfsdclnts \-\-clientinfo\fP
|
||||||
|
+.RS 4
|
||||||
|
+Print client information.
|
||||||
|
+.RE
|
||||||
|
+.sp
|
||||||
|
+.if n .RS 4
|
||||||
|
+.nf
|
||||||
|
+Inode number | Type | Access | Deny | ip address | Client ID | vers | Filename
|
||||||
|
+33823232 | open | r\- | \-\- | [::1]:757 | 0xc79a009f5eb65e84 | 4.2 | testfile
|
||||||
|
+33823232 | deleg | r | | [::1]:757 | 0xc79a009f5eb65e84 | 4.2 | testfile
|
||||||
|
+.fi
|
||||||
|
+.if n .RE
|
||||||
|
+.sp
|
||||||
|
+\fBnfsdclnts \-\-file /proc/fs/nfsd/clients/3/states -t open\fP
|
||||||
|
+.RS 4
|
||||||
|
+Process specific states file.
|
||||||
|
+.RE
|
||||||
|
+.sp
|
||||||
|
+.if n .RS 4
|
||||||
|
+.nf
|
||||||
|
+Inode number | Type | Access | Deny | ip address | Client ID | vers | Filename
|
||||||
|
+33823232 | open | r\- | \-\- | [::1]:757 | 0xc79a009f5eb65e84 | 4.2 | testfile
|
||||||
|
+.fi
|
||||||
|
+.if n .RE
|
||||||
|
+.sp
|
||||||
|
+\fBnfsdclnts \-\-quiet \-\-hostname\fP
|
||||||
|
+.RS 4
|
||||||
|
+Hide the header information.
|
||||||
|
+.RE
|
||||||
|
+.sp
|
||||||
|
+.if n .RS 4
|
||||||
|
+.nf
|
||||||
|
+33823232 | open | r\- | \-\- | nfs\-server | testfile
|
||||||
|
+33823232 | deleg | r | | nfs\-server | testfile
|
||||||
|
+.fi
|
||||||
|
+.if n .RE
|
||||||
|
+.SH "FILES"
|
||||||
|
+.sp
|
||||||
|
+\fB/proc/fs/nfsd/clients/\fP
|
||||||
|
+.sp
|
||||||
|
+Displays basic information about each NFSv4 client.
|
||||||
|
+.sp
|
||||||
|
+\fB/proc/fs/nfsd/clients/#/info\fP
|
||||||
|
+.sp
|
||||||
|
+Displays information about all the opens held by the given client, including open modes, device numbers, inode numbers, and open owners.
|
||||||
|
+.sp
|
||||||
|
+\fB/proc/fs/nfsd/clients/#/states\fP
|
||||||
|
+.SH "NOTES"
|
||||||
|
+.sp
|
||||||
|
+/proc/fs/nfsd/clients/ support was initially introduced in 5.3 kernel and is only implemented for mount points using NFSv4.
|
||||||
|
+.SH "BUGS"
|
||||||
|
+Please report any BUGs to \c
|
||||||
|
+.MTO "linux\-nfs\(atvger.kernel.org" "" ""
|
||||||
|
+.SH SEE ALSO
|
||||||
|
+.BR nfsd (8),
|
||||||
|
+.BR exportfs (8),
|
||||||
|
+.BR idmapd (8),
|
||||||
|
+.BR statd (8)
|
||||||
|
+.SH "AUTHORS"
|
||||||
|
+Achilles Gaikwad <agaikwad@redhat.com> and
|
||||||
|
+Kenneth D'souza <kdsouza@redhat.com>
|
||||||
|
diff -up nfs-utils-2.3.3/tools/nfsdclnts/nfsdclnts.py.orig nfs-utils-2.3.3/tools/nfsdclnts/nfsdclnts.py
|
||||||
|
--- nfs-utils-2.3.3/tools/nfsdclnts/nfsdclnts.py.orig 2020-06-09 11:02:04.203102954 -0400
|
||||||
|
+++ nfs-utils-2.3.3/tools/nfsdclnts/nfsdclnts.py 2020-06-09 11:02:04.203102954 -0400
|
||||||
|
@@ -0,0 +1,254 @@
|
||||||
|
+#!/usr/bin/python3
|
||||||
|
+# -*- python-mode -*-
|
||||||
|
+'''
|
||||||
|
+ Copyright (C) 2020
|
||||||
|
+ Authors: Achilles Gaikwad <agaikwad@redhat.com>
|
||||||
|
+ Kenneth D'souza <kdsouza@redhat.com>
|
||||||
|
+
|
||||||
|
+ This program is free software: you can redistribute it and/or modify
|
||||||
|
+ it under the terms of the GNU General Public License as published by
|
||||||
|
+ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
+ (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ This program is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ GNU General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU General Public License
|
||||||
|
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
+'''
|
||||||
|
+
|
||||||
|
+import multiprocessing as mp
|
||||||
|
+import os
|
||||||
|
+import signal
|
||||||
|
+import sys
|
||||||
|
+
|
||||||
|
+try:
|
||||||
|
+ import argparse
|
||||||
|
+except ImportError:
|
||||||
|
+ print('%s: Failed to import argparse - make sure argparse is installed!'
|
||||||
|
+ % sys.argv[0])
|
||||||
|
+ sys.exit(1)
|
||||||
|
+try:
|
||||||
|
+ import yaml
|
||||||
|
+except ImportError:
|
||||||
|
+ print('%s: Failed to import yaml - make sure python3-pyyaml is installed!'
|
||||||
|
+ % sys.argv[0])
|
||||||
|
+ sys.exit(1)
|
||||||
|
+
|
||||||
|
+BBOLD = '\033[1;30;47m' #Bold black text with white background.
|
||||||
|
+ENDC = '\033[m' #Rest to defaults
|
||||||
|
+
|
||||||
|
+def init_worker():
|
||||||
|
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
|
||||||
|
+
|
||||||
|
+# this function converts the info file to a dictionary format, sorta.
|
||||||
|
+def file_to_dict(path):
|
||||||
|
+ client_info = {}
|
||||||
|
+ try:
|
||||||
|
+ with open(path) as f:
|
||||||
|
+ for line in f:
|
||||||
|
+ try:
|
||||||
|
+ (key, val) = line.split(':', 1)
|
||||||
|
+ client_info[key] = val.strip()
|
||||||
|
+ # FIXME: There has to be a better way of converting the info file to a dictionary.
|
||||||
|
+ except ValueError as reason:
|
||||||
|
+ if verbose:
|
||||||
|
+ print('Exception occured, %s' % reason)
|
||||||
|
+
|
||||||
|
+ if len(client_info) == 0 and verbose:
|
||||||
|
+ print("Provided %s file is not valid" %path)
|
||||||
|
+ return client_info
|
||||||
|
+
|
||||||
|
+ except OSError as reason:
|
||||||
|
+ if verbose:
|
||||||
|
+ print('%s' % reason)
|
||||||
|
+
|
||||||
|
+# this function gets the paths from /proc/fs/nfsd/clients/
|
||||||
|
+# returns a list of paths for each client which has nfs-share mounted.
|
||||||
|
+def getpaths():
|
||||||
|
+ path = []
|
||||||
|
+ try:
|
||||||
|
+ dirs = os.listdir('/proc/fs/nfsd/clients/')
|
||||||
|
+ except OSError as reason:
|
||||||
|
+ exit('%s' % reason)
|
||||||
|
+ if len(dirs) !=0:
|
||||||
|
+ for i in dirs:
|
||||||
|
+ path.append('/proc/fs/nfsd/clients/' + i + '/states')
|
||||||
|
+ return (path)
|
||||||
|
+ else:
|
||||||
|
+ exit('Nothing to process')
|
||||||
|
+
|
||||||
|
+# A single function to rule them all, in this function we gather all the data
|
||||||
|
+# from already populated data_list and client_info.
|
||||||
|
+def printer(data_list, argument):
|
||||||
|
+ client_info_path = data_list.pop()
|
||||||
|
+ client_info = file_to_dict(client_info_path)
|
||||||
|
+ for i in data_list:
|
||||||
|
+ for key in i:
|
||||||
|
+ inode = i[key]['superblock'].split(':')[-1]
|
||||||
|
+ # The ip address is quoted, so we dequote it.
|
||||||
|
+ try:
|
||||||
|
+ client_ip = client_info['address'][1:-1]
|
||||||
|
+ except:
|
||||||
|
+ client_ip = "N/A"
|
||||||
|
+ try:
|
||||||
|
+ # if the nfs-server reboots while the nfs-client holds the files open,
|
||||||
|
+ # the nfs-server would print the filename as '/'. For such instaces we
|
||||||
|
+ # print the output as disconnected dentry instead of '/'.
|
||||||
|
+ if(i[key]['filename']=='/'):
|
||||||
|
+ fname = 'disconnected dentry'
|
||||||
|
+ else:
|
||||||
|
+ fname = i[key]['filename'].split('/')[-1]
|
||||||
|
+ except KeyError:
|
||||||
|
+ # for older kernels which do not have the fname patch in kernel, they
|
||||||
|
+ # won't be able to see the fname field. Therefore post it as N/A.
|
||||||
|
+ fname = "N/A"
|
||||||
|
+ otype = i[key]['type']
|
||||||
|
+ try:
|
||||||
|
+ access = i[key]['access']
|
||||||
|
+ except:
|
||||||
|
+ access = ''
|
||||||
|
+ try:
|
||||||
|
+ deny = i[key]['deny']
|
||||||
|
+ except:
|
||||||
|
+ deny = ''
|
||||||
|
+ try:
|
||||||
|
+ hostname = client_info['name'].split()[-1].split('"')[0]
|
||||||
|
+ hostname = hostname.split('.')[0]
|
||||||
|
+ # if the hostname is too long, it messes up with the output being in columns,
|
||||||
|
+ # therefore we truncate the hostname followed by two '..' as suffix.
|
||||||
|
+ if len(hostname) > 20:
|
||||||
|
+ hostname = hostname[0:20] + '..'
|
||||||
|
+ except:
|
||||||
|
+ hostname = "N/A"
|
||||||
|
+ try:
|
||||||
|
+ clientid = client_info['clientid']
|
||||||
|
+ except:
|
||||||
|
+ clientid = "N/A"
|
||||||
|
+ try:
|
||||||
|
+ minorversion = "4." + client_info['minor version']
|
||||||
|
+ except:
|
||||||
|
+ minorversion = "N/A"
|
||||||
|
+
|
||||||
|
+ otype = i[key]['type']
|
||||||
|
+ # since some fields do not have deny column, we drop those if -t is either
|
||||||
|
+ # layout or lock.
|
||||||
|
+ drop = ['layout', 'lock']
|
||||||
|
+
|
||||||
|
+ # Printing the output this way instead of a single string which is concatenated
|
||||||
|
+ # this makes it better to quickly add more columns in future.
|
||||||
|
+ if(otype == argument.type or argument.type == 'all'):
|
||||||
|
+ print('%-13s' %inode, end='| ')
|
||||||
|
+ print('%-7s' %otype, end='| ')
|
||||||
|
+ if (argument.type not in drop):
|
||||||
|
+ print('%-7s' %access, end='| ')
|
||||||
|
+ if (argument.type not in drop and argument.type !='deleg'):
|
||||||
|
+ print('%-5s' %deny, end='| ')
|
||||||
|
+ if (argument.hostname == True):
|
||||||
|
+ print('%-22s' %hostname, end='| ')
|
||||||
|
+ else:
|
||||||
|
+ print('%-22s' %client_ip, end='| ')
|
||||||
|
+ if (argument.clientinfo == True) :
|
||||||
|
+ print('%-20s' %clientid, end='| ')
|
||||||
|
+ print('%-5s' %minorversion, end='| ')
|
||||||
|
+ print(fname)
|
||||||
|
+
|
||||||
|
+def opener(path):
|
||||||
|
+ try:
|
||||||
|
+ with open(path, 'r') as nfsdata:
|
||||||
|
+ try:
|
||||||
|
+ data = yaml.load(nfsdata, Loader = yaml.BaseLoader)
|
||||||
|
+ if data is not None:
|
||||||
|
+ clientinfo = path.rsplit('/', 1)[0] + '/info'
|
||||||
|
+ data.append(clientinfo)
|
||||||
|
+ return data
|
||||||
|
+ except:
|
||||||
|
+ if verbose:
|
||||||
|
+ print("Exception occurred, Please make sure %s is a YAML file" %path)
|
||||||
|
+
|
||||||
|
+ except OSError as reason:
|
||||||
|
+ if verbose:
|
||||||
|
+ print('%s' % reason)
|
||||||
|
+
|
||||||
|
+def print_cols(argument):
|
||||||
|
+ title_inode = 'Inode number'
|
||||||
|
+ title_otype = 'Type'
|
||||||
|
+ title_access = 'Access'
|
||||||
|
+ title_deny = 'Deny'
|
||||||
|
+ title_fname = 'Filename'
|
||||||
|
+ title_clientID = 'Client ID'
|
||||||
|
+ title_hostname = 'Hostname'
|
||||||
|
+ title_ip = 'ip address'
|
||||||
|
+ title_nfsvers = 'vers'
|
||||||
|
+
|
||||||
|
+ drop = ['lock', 'layout']
|
||||||
|
+ print(BBOLD, end='')
|
||||||
|
+ print('%-13s' %title_inode, end='| ')
|
||||||
|
+ print('%-7s' %title_otype, end='| ')
|
||||||
|
+ if (argument.type not in drop):
|
||||||
|
+ print('%-7s' %title_access, end='| ')
|
||||||
|
+ if (argument.type not in drop and argument.type !='deleg'):
|
||||||
|
+ print('%-5s' %title_deny, end='| ')
|
||||||
|
+ if (argument.hostname == True):
|
||||||
|
+ print('%-22s' %title_hostname, end='| ')
|
||||||
|
+ else:
|
||||||
|
+ print('%-22s' %title_ip, end='| ')
|
||||||
|
+ if (argument.clientinfo == True):
|
||||||
|
+ print('%-20s' %title_clientID, end='| ')
|
||||||
|
+ print('%-5s' %title_nfsvers, end='| ')
|
||||||
|
+ print(title_fname, end='')
|
||||||
|
+ print(ENDC)
|
||||||
|
+
|
||||||
|
+def nfsd4_show():
|
||||||
|
+
|
||||||
|
+ parser = argparse.ArgumentParser(description = 'Parse the nfsd states and clientinfo files.')
|
||||||
|
+ parser.add_argument('-t', '--type', metavar = 'type', type = str, choices = ['open',
|
||||||
|
+ 'deleg', 'lock', 'layout', 'all'],
|
||||||
|
+ default = 'all',
|
||||||
|
+ help = 'Input the type that you want to be printed: open, lock, deleg, layout, all')
|
||||||
|
+ parser.add_argument('--clientinfo', action = 'store_true',
|
||||||
|
+ help = 'output clients information, --hostname is implied.')
|
||||||
|
+ parser.add_argument('--hostname', action = 'store_true',
|
||||||
|
+ help = 'print hostname of client instead of its ip address. Longer hostnames are truncated.')
|
||||||
|
+ parser.add_argument('-v', '--verbose', action = 'store_true',
|
||||||
|
+ help = 'Verbose operation, show debug messages.')
|
||||||
|
+ parser.add_argument('-f', '--file', nargs='+', type = str, metavar='',
|
||||||
|
+ help = 'pass client states file, provided that info file resides in the same directory.')
|
||||||
|
+ parser.add_argument('-q', '--quiet', action = 'store_true',
|
||||||
|
+ help = 'don\'t print the header information')
|
||||||
|
+
|
||||||
|
+ args = parser.parse_args()
|
||||||
|
+
|
||||||
|
+ global verbose
|
||||||
|
+ verbose = False
|
||||||
|
+ if args.verbose:
|
||||||
|
+ verbose = True
|
||||||
|
+
|
||||||
|
+ if args.file:
|
||||||
|
+ paths = args.file
|
||||||
|
+ else:
|
||||||
|
+ paths = getpaths()
|
||||||
|
+
|
||||||
|
+ p = mp.Pool(mp.cpu_count(), init_worker)
|
||||||
|
+ try:
|
||||||
|
+ result = p.map(opener, paths)
|
||||||
|
+ ### Drop None entries from list
|
||||||
|
+ final_result = list(filter(None, result))
|
||||||
|
+ p.close()
|
||||||
|
+ p.join()
|
||||||
|
+
|
||||||
|
+ if len(final_result) !=0 and not args.quiet:
|
||||||
|
+ print_cols(args)
|
||||||
|
+
|
||||||
|
+ for item in final_result:
|
||||||
|
+ printer(item, args)
|
||||||
|
+
|
||||||
|
+ except KeyboardInterrupt:
|
||||||
|
+ print('Caught KeyboardInterrupt, terminating workers')
|
||||||
|
+ p.terminate()
|
||||||
|
+ p.join()
|
||||||
|
+
|
||||||
|
+if __name__ == "__main__":
|
||||||
|
+ nfsd4_show()
|
4048
SOURCES/nfs-utils-2.3.3-nfsdcld-upstream-update.patch
Normal file
4048
SOURCES/nfs-utils-2.3.3-nfsdcld-upstream-update.patch
Normal file
File diff suppressed because it is too large
Load Diff
29
SOURCES/nfs-utils-2.3.3-nfsdclddb-manpage-rename.patch
Normal file
29
SOURCES/nfs-utils-2.3.3-nfsdclddb-manpage-rename.patch
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
commit 3e81185037cf97990e4598218f56d92dd70d6269
|
||||||
|
Author: NeilBrown <neilb@suse.de>
|
||||||
|
Date: Tue Oct 20 13:19:10 2020 -0400
|
||||||
|
|
||||||
|
clddb-tool was recently renamed to nfsdclddb.
|
||||||
|
Unfortunately the nfsdcld man page wasn't told.
|
||||||
|
|
||||||
|
Signed-off-by: NeilBrown <neilb@suse.de>
|
||||||
|
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/utils/nfsdcld/nfsdcld.man b/utils/nfsdcld/nfsdcld.man
|
||||||
|
index 4c2b1e80..861f1c49 100644
|
||||||
|
--- a/utils/nfsdcld/nfsdcld.man
|
||||||
|
+++ b/utils/nfsdcld/nfsdcld.man
|
||||||
|
@@ -209,12 +209,12 @@ not necessary after upgrading \fBnfsdcld\fR, however \fBnfsd\fR will not use a l
|
||||||
|
version until restart. A restart of \fBnfsd is necessary\fR after downgrading \fBnfsdcld\fR,
|
||||||
|
to ensure that \fBnfsd\fR does not use an upcall version that \fBnfsdcld\fR does not support.
|
||||||
|
Additionally, a downgrade of \fBnfsdcld\fR requires the schema of the on-disk database to
|
||||||
|
-be downgraded as well. That can be accomplished using the \fBclddb-tool\fR(8) utility.
|
||||||
|
+be downgraded as well. That can be accomplished using the \fBnfsdclddb\fR(8) utility.
|
||||||
|
.SH FILES
|
||||||
|
.TP
|
||||||
|
.B /var/lib/nfs/nfsdcld/main.sqlite
|
||||||
|
.SH SEE ALSO
|
||||||
|
-.BR nfsdcltrack "(8), " clddb-tool (8)
|
||||||
|
+.BR nfsdcltrack "(8), " nfsdclddb (8)
|
||||||
|
.SH "AUTHORS"
|
||||||
|
.IX Header "AUTHORS"
|
||||||
|
The nfsdcld daemon was developed by Jeff Layton <jlayton@redhat.com>
|
130
SOURCES/nfs-utils-2.3.3-nfsdclddb-rename.patch
Normal file
130
SOURCES/nfs-utils-2.3.3-nfsdclddb-rename.patch
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
commit 77d053e4881664e7dbbc3bbb9a242af005598e95
|
||||||
|
Author: Steve Dickson <steved@redhat.com>
|
||||||
|
Date: Wed May 13 12:22:41 2020 -0400
|
||||||
|
|
||||||
|
nfsdclddb: Redname clddb-tool to nfsdclddb
|
||||||
|
|
||||||
|
To try to maintain some type of name convention
|
||||||
|
rename clddb-tool to nfsdclddb
|
||||||
|
|
||||||
|
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/configure.ac b/configure.ac
|
||||||
|
index df88e58..0b1c8cc 100644
|
||||||
|
--- a/configure.ac
|
||||||
|
+++ b/configure.ac
|
||||||
|
@@ -695,7 +695,7 @@ AC_CONFIG_FILES([
|
||||||
|
tools/mountstats/Makefile
|
||||||
|
tools/nfs-iostat/Makefile
|
||||||
|
tools/nfsconf/Makefile
|
||||||
|
- tools/clddb-tool/Makefile
|
||||||
|
+ tools/nfsdclddb/Makefile
|
||||||
|
utils/Makefile
|
||||||
|
utils/blkmapd/Makefile
|
||||||
|
utils/nfsdcld/Makefile
|
||||||
|
diff --git a/tools/Makefile.am b/tools/Makefile.am
|
||||||
|
index 53e6117..432d35d 100644
|
||||||
|
--- a/tools/Makefile.am
|
||||||
|
+++ b/tools/Makefile.am
|
||||||
|
@@ -9,7 +9,7 @@ endif
|
||||||
|
OPTDIRS += nfsconf
|
||||||
|
|
||||||
|
if CONFIG_NFSDCLD
|
||||||
|
-OPTDIRS += clddb-tool
|
||||||
|
+OPTDIRS += nfsdclddb
|
||||||
|
endif
|
||||||
|
|
||||||
|
SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat $(OPTDIRS)
|
||||||
|
diff --git a/tools/clddb-tool/Makefile.am b/tools/nfsdclddb/Makefile.am
|
||||||
|
similarity index 60%
|
||||||
|
rename from tools/clddb-tool/Makefile.am
|
||||||
|
rename to tools/nfsdclddb/Makefile.am
|
||||||
|
index 15a8fd4..18263fb 100644
|
||||||
|
--- a/tools/clddb-tool/Makefile.am
|
||||||
|
+++ b/tools/nfsdclddb/Makefile.am
|
||||||
|
@@ -1,13 +1,13 @@
|
||||||
|
## Process this file with automake to produce Makefile.in
|
||||||
|
-PYTHON_FILES = clddb-tool.py
|
||||||
|
+PYTHON_FILES = nfsdclddb.py
|
||||||
|
|
||||||
|
-man8_MANS = clddb-tool.man
|
||||||
|
+man8_MANS = nfsdclddb.man
|
||||||
|
|
||||||
|
EXTRA_DIST = $(man8_MANS) $(PYTHON_FILES)
|
||||||
|
|
||||||
|
all-local: $(PYTHON_FILES)
|
||||||
|
|
||||||
|
install-data-hook:
|
||||||
|
- $(INSTALL) -m 755 clddb-tool.py $(DESTDIR)$(sbindir)/clddb-tool
|
||||||
|
+ $(INSTALL) -m 755 nfsdclddb.py $(DESTDIR)$(sbindir)/nfsdclddb
|
||||||
|
|
||||||
|
MAINTAINERCLEANFILES=Makefile.in
|
||||||
|
diff --git a/tools/clddb-tool/clddb-tool.man b/tools/nfsdclddb/nfsdclddb.man
|
||||||
|
similarity index 84%
|
||||||
|
rename from tools/clddb-tool/clddb-tool.man
|
||||||
|
rename to tools/nfsdclddb/nfsdclddb.man
|
||||||
|
index e80b2c0..8ec7b18 100644
|
||||||
|
--- a/tools/clddb-tool/clddb-tool.man
|
||||||
|
+++ b/tools/nfsdclddb/nfsdclddb.man
|
||||||
|
@@ -1,20 +1,20 @@
|
||||||
|
.\"
|
||||||
|
-.\" clddb-tool(8)
|
||||||
|
+.\" nfsdclddb(8)
|
||||||
|
.\"
|
||||||
|
-.TH clddb-tool 8 "07 Aug 2019"
|
||||||
|
+.TH nfsdclddb 8 "07 Aug 2019"
|
||||||
|
.SH NAME
|
||||||
|
-clddb-tool \- Tool for manipulating the nfsdcld sqlite database
|
||||||
|
+nfsdclddb \- Tool for manipulating the nfsdcld sqlite database
|
||||||
|
.SH SYNOPSIS
|
||||||
|
-.B clddb-tool
|
||||||
|
+.B nfsdclddb
|
||||||
|
.RB [ \-h | \-\-help ]
|
||||||
|
.P
|
||||||
|
-.B clddb-tool
|
||||||
|
+.B nfsdclddb
|
||||||
|
.RB [ \-p | \-\-path
|
||||||
|
.IR dbpath ]
|
||||||
|
.B fix-table-names
|
||||||
|
.RB [ \-h | \-\-help ]
|
||||||
|
.P
|
||||||
|
-.B clddb-tool
|
||||||
|
+.B nfsdclddb
|
||||||
|
.RB [ \-p | \-\-path
|
||||||
|
.IR dbpath ]
|
||||||
|
.B downgrade-schema
|
||||||
|
@@ -22,7 +22,7 @@ clddb-tool \- Tool for manipulating the nfsdcld sqlite database
|
||||||
|
.RB [ \-v | \-\-version
|
||||||
|
.IR to-version ]
|
||||||
|
.P
|
||||||
|
-.B clddb-tool
|
||||||
|
+.B nfsdclddb
|
||||||
|
.RB [ \-p | \-\-path
|
||||||
|
.IR dbpath ]
|
||||||
|
.B print
|
||||||
|
@@ -31,10 +31,10 @@ clddb-tool \- Tool for manipulating the nfsdcld sqlite database
|
||||||
|
.P
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
-.RB "The " clddb-tool " command is provided to perform some manipulation of the nfsdcld sqlite database schema and to print the contents of the database."
|
||||||
|
+.RB "The " nfsdclddb " command is provided to perform some manipulation of the nfsdcld sqlite database schema and to print the contents of the database."
|
||||||
|
.SS Sub-commands
|
||||||
|
Valid
|
||||||
|
-.B clddb-tool
|
||||||
|
+.B nfsdclddb
|
||||||
|
subcommands are:
|
||||||
|
.IP "\fBfix-table-names\fP"
|
||||||
|
.RB "A previous version of " nfsdcld "(8) contained a bug that corrupted the reboot epoch table names. This sub-command will fix those table names."
|
||||||
|
@@ -66,7 +66,7 @@ The schema version to downgrade to. Currently the schema can only be downgraded
|
||||||
|
Do not list the clients in the reboot epoch tables in the output.
|
||||||
|
.SH NOTES
|
||||||
|
The
|
||||||
|
-.B clddb-tool
|
||||||
|
+.B nfsdclddb
|
||||||
|
command will not allow the
|
||||||
|
.B fix-table-names
|
||||||
|
or
|
||||||
|
diff --git a/tools/clddb-tool/clddb-tool.py b/tools/nfsdclddb/nfsdclddb.py
|
||||||
|
similarity index 100%
|
||||||
|
rename from tools/clddb-tool/clddb-tool.py
|
||||||
|
rename to tools/nfsdclddb/nfsdclddb.py
|
27
SOURCES/nfs-utils-2.3.3-nfsidmap-debug.patch
Normal file
27
SOURCES/nfs-utils-2.3.3-nfsidmap-debug.patch
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
commit 0095435db8228d5a88ec35a63cb64271e2e648a8
|
||||||
|
Author: Steve Dickson <steved@redhat.com>
|
||||||
|
Date: Thu Dec 19 12:48:31 2019 -0500
|
||||||
|
|
||||||
|
libnfsidmap: Turn off default verbosity
|
||||||
|
|
||||||
|
Commit f080188e changed the library's verbosity
|
||||||
|
to be on by default. The patch turns it off by
|
||||||
|
default
|
||||||
|
|
||||||
|
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1774787
|
||||||
|
|
||||||
|
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/support/nfsidmap/libnfsidmap.c b/support/nfsidmap/libnfsidmap.c
|
||||||
|
index 9299e652..d11710f1 100644
|
||||||
|
--- a/support/nfsidmap/libnfsidmap.c
|
||||||
|
+++ b/support/nfsidmap/libnfsidmap.c
|
||||||
|
@@ -101,7 +101,7 @@ static void default_logger(const char *fmt, ...)
|
||||||
|
|
||||||
|
#pragma GCC visibility pop
|
||||||
|
nfs4_idmap_log_function_t idmap_log_func = default_logger;
|
||||||
|
-int idmap_verbosity = 2;
|
||||||
|
+int idmap_verbosity = 0;
|
||||||
|
#pragma GCC visibility push(hidden)
|
||||||
|
|
||||||
|
static int id_as_chars(char *name, uid_t *id)
|
12
SOURCES/nfs-utils-2.3.3-nfsiostat-div-zero.patch
Normal file
12
SOURCES/nfs-utils-2.3.3-nfsiostat-div-zero.patch
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
diff -up nfs-utils-2.3.3/tools/nfs-iostat/nfs-iostat.py.orig nfs-utils-2.3.3/tools/nfs-iostat/nfs-iostat.py
|
||||||
|
--- nfs-utils-2.3.3/tools/nfs-iostat/nfs-iostat.py.orig 2020-12-10 10:38:26.462195326 -0500
|
||||||
|
+++ nfs-utils-2.3.3/tools/nfs-iostat/nfs-iostat.py 2020-12-10 10:45:47.210671473 -0500
|
||||||
|
@@ -380,6 +380,8 @@ class DeviceData:
|
||||||
|
sends = float(self.__rpc_data['rpcsends'])
|
||||||
|
if sample_time == 0:
|
||||||
|
sample_time = float(self.__nfs_data['age'])
|
||||||
|
+ if sample_time == 0:
|
||||||
|
+ sample_time = 1;
|
||||||
|
return (sends / sample_time)
|
||||||
|
|
||||||
|
def display_iostats(self, sample_time, which):
|
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
|
37
SOURCES/nfs-utils-2.3.3-nfsiostat-key-error.patch
Normal file
37
SOURCES/nfs-utils-2.3.3-nfsiostat-key-error.patch
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
diff -up nfs-utils-2.3.3/tools/mountstats/mountstats.py.orig nfs-utils-2.3.3/tools/mountstats/mountstats.py
|
||||||
|
--- nfs-utils-2.3.3/tools/mountstats/mountstats.py.orig 2020-12-10 10:48:17.319579958 -0500
|
||||||
|
+++ nfs-utils-2.3.3/tools/mountstats/mountstats.py 2020-12-10 10:52:42.481484160 -0500
|
||||||
|
@@ -943,10 +943,11 @@ def print_iostat_summary(old, new, devic
|
||||||
|
if not old or device not in old:
|
||||||
|
stats.display_iostats(time)
|
||||||
|
else:
|
||||||
|
- old_stats = DeviceData()
|
||||||
|
- old_stats.parse_stats(old[device])
|
||||||
|
- diff_stats = stats.compare_iostats(old_stats)
|
||||||
|
- diff_stats.display_iostats(time)
|
||||||
|
+ 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 iostat_command(args):
|
||||||
|
"""iostat-like command for NFS mount points
|
||||||
|
diff -up nfs-utils-2.3.3/tools/nfs-iostat/nfs-iostat.py.orig nfs-utils-2.3.3/tools/nfs-iostat/nfs-iostat.py
|
||||||
|
--- nfs-utils-2.3.3/tools/nfs-iostat/nfs-iostat.py.orig 2020-12-10 10:48:17.316579880 -0500
|
||||||
|
+++ nfs-utils-2.3.3/tools/nfs-iostat/nfs-iostat.py 2020-12-10 10:52:42.481484160 -0500
|
||||||
|
@@ -467,10 +467,13 @@ def parse_stats_file(filename):
|
||||||
|
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
|
||||||
|
- devicelist = [x for x in old if x in devices]
|
||||||
|
+ for device in devices:
|
||||||
|
+ if "fstype autofs" not in str(old[device]):
|
||||||
|
+ devicelist.append(device)
|
||||||
|
else:
|
||||||
|
devicelist = devices
|
||||||
|
|
53
SOURCES/nfs-utils-2.3.3-nfsman-softreval.patch
Normal file
53
SOURCES/nfs-utils-2.3.3-nfsman-softreval.patch
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
commit b5381c96298d75ba66625a007e2390e2b501850d
|
||||||
|
Author: Trond Myklebust <trond.myklebust@hammerspace.com>
|
||||||
|
Date: Wed Jan 29 10:45:39 2020 -0500
|
||||||
|
|
||||||
|
manpage: Add a description of the 'softreval' / 'nosoftreval' mount option
|
||||||
|
|
||||||
|
Add a description of the 'softreval' / 'nosoftreval' mount options on
|
||||||
|
the 'nfs' generic manpage.
|
||||||
|
|
||||||
|
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
|
||||||
|
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/utils/mount/nfs.man b/utils/mount/nfs.man
|
||||||
|
index 84462cd7..6f79c63a 100644
|
||||||
|
--- a/utils/mount/nfs.man
|
||||||
|
+++ b/utils/mount/nfs.man
|
||||||
|
@@ -121,6 +121,36 @@ option may mitigate some of the risks of using the
|
||||||
|
.B soft
|
||||||
|
option.
|
||||||
|
.TP 1.5i
|
||||||
|
+.BR softreval " / " nosoftreval
|
||||||
|
+In cases where the NFS server is down, it may be useful to
|
||||||
|
+allow the NFS client to continue to serve up paths and
|
||||||
|
+attributes from cache after
|
||||||
|
+.B retrans
|
||||||
|
+attempts to revalidate that cache have timed out.
|
||||||
|
+This may, for instance, be helpful when trying to unmount a
|
||||||
|
+filesystem tree from a server that is permanently down.
|
||||||
|
+.IP
|
||||||
|
+It is possible to combine
|
||||||
|
+.BR softreval
|
||||||
|
+with the
|
||||||
|
+.B soft
|
||||||
|
+mount option, in which case operations that cannot be served up
|
||||||
|
+from cache will time out and return an error after
|
||||||
|
+.B retrans
|
||||||
|
+attempts. The combination with the default
|
||||||
|
+.B hard
|
||||||
|
+mount option implies those uncached operations will continue to
|
||||||
|
+retry until a response is received from the server.
|
||||||
|
+.IP
|
||||||
|
+Note: the default mount option is
|
||||||
|
+.BR nosoftreval
|
||||||
|
+which disallows fallback to cache when revalidation fails, and
|
||||||
|
+instead follows the behavior dictated by the
|
||||||
|
+.B hard
|
||||||
|
+or
|
||||||
|
+.B soft
|
||||||
|
+mount option.
|
||||||
|
+.TP 1.5i
|
||||||
|
.BR intr " / " nointr
|
||||||
|
This option is provided for backward compatibility.
|
||||||
|
It is ignored after kernel 2.6.25.
|
399
SOURCES/nfs-utils-2.3.3-nfsrahead.patch
Normal file
399
SOURCES/nfs-utils-2.3.3-nfsrahead.patch
Normal file
@ -0,0 +1,399 @@
|
|||||||
|
diff --git a/.gitignore b/.gitignore
|
||||||
|
index e97b31f5..e504d492 100644
|
||||||
|
--- a/.gitignore
|
||||||
|
+++ b/.gitignore
|
||||||
|
@@ -60,6 +60,8 @@ utils/statd/statd
|
||||||
|
tools/locktest/testlk
|
||||||
|
tools/getiversion/getiversion
|
||||||
|
tools/nfsconf/nfsconf
|
||||||
|
+tools/nfsrahead/nfsrahead
|
||||||
|
+tools/nfsrahead/99-nfs_bdi.rules
|
||||||
|
support/export/mount.h
|
||||||
|
support/export/mount_clnt.c
|
||||||
|
support/export/mount_xdr.c
|
||||||
|
diff --git a/configure.ac b/configure.ac
|
||||||
|
index 6d464ac5..f462a645 100644
|
||||||
|
--- a/configure.ac
|
||||||
|
+++ b/configure.ac
|
||||||
|
@@ -639,6 +639,7 @@ AC_CONFIG_FILES([
|
||||||
|
tools/rpcgen/Makefile
|
||||||
|
tools/mountstats/Makefile
|
||||||
|
tools/nfs-iostat/Makefile
|
||||||
|
+ tools/nfsrahead/Makefile
|
||||||
|
tools/rpcctl/Makefile
|
||||||
|
tools/nfsdclnts/Makefile
|
||||||
|
tools/nfsconf/Makefile
|
||||||
|
diff --git a/nfs.conf b/nfs.conf
|
||||||
|
index 86ed7d53..30f9e109 100644
|
||||||
|
--- a/nfs.conf
|
||||||
|
+++ b/nfs.conf
|
||||||
|
@@ -5,6 +5,10 @@
|
||||||
|
[general]
|
||||||
|
# pipefs-directory=/var/lib/nfs/rpc_pipefs
|
||||||
|
#
|
||||||
|
+[nfsrahead]
|
||||||
|
+# nfs=15000
|
||||||
|
+# nfs4=16000
|
||||||
|
+#
|
||||||
|
[exportfs]
|
||||||
|
# debug=0
|
||||||
|
#
|
||||||
|
diff --git a/systemd/nfs.conf.man b/systemd/nfs.conf.man
|
||||||
|
index f32c690b..ebbf28d0 100644
|
||||||
|
--- a/systemd/nfs.conf.man
|
||||||
|
+++ b/systemd/nfs.conf.man
|
||||||
|
@@ -245,6 +245,17 @@ Only
|
||||||
|
.B debug=
|
||||||
|
is recognized.
|
||||||
|
|
||||||
|
+.TP
|
||||||
|
+.B nfsrahead
|
||||||
|
+Recognized values:
|
||||||
|
+.BR nfs ,
|
||||||
|
+.BR nfsv4 ,
|
||||||
|
+.BR default .
|
||||||
|
+
|
||||||
|
+See
|
||||||
|
+.BR nfsrahead (5)
|
||||||
|
+for deatils.
|
||||||
|
+
|
||||||
|
.SH FILES
|
||||||
|
.I /etc/nfs.conf
|
||||||
|
.SH SEE ALSO
|
||||||
|
diff --git a/tools/Makefile.am b/tools/Makefile.am
|
||||||
|
index c3feabbe..40c17c37 100644
|
||||||
|
--- a/tools/Makefile.am
|
||||||
|
+++ b/tools/Makefile.am
|
||||||
|
@@ -12,6 +12,6 @@ if CONFIG_NFSDCLD
|
||||||
|
OPTDIRS += nfsdclddb
|
||||||
|
endif
|
||||||
|
|
||||||
|
-SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat rpcctl nfsdclnts $(OPTDIRS)
|
||||||
|
+SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat rpcctl nfsdclnts nfsrahead $(OPTDIRS)
|
||||||
|
|
||||||
|
MAINTAINERCLEANFILES = Makefile.in
|
||||||
|
diff --git a/tools/nfsrahead/99-nfs.rules b/tools/nfsrahead/99-nfs.rules
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..c74914b2
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tools/nfsrahead/99-nfs.rules
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+SUBSYSTEM=="bdi", ACTION=="add", PROGRAM="/usr/libexec/nfsrahead %k", ATTR{read_ahead_kb}="%c"
|
||||||
|
diff --git a/tools/nfsrahead/99-nfs.rules.in b/tools/nfsrahead/99-nfs.rules.in
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..648813c5
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tools/nfsrahead/99-nfs.rules.in
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+SUBSYSTEM=="bdi", ACTION=="add", PROGRAM="_libexecdir_/nfsrahead %k", ATTR{read_ahead_kb}="%c"
|
||||||
|
diff --git a/tools/nfsrahead/Makefile.am b/tools/nfsrahead/Makefile.am
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..845ea0d5
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tools/nfsrahead/Makefile.am
|
||||||
|
@@ -0,0 +1,16 @@
|
||||||
|
+libexec_PROGRAMS = nfsrahead
|
||||||
|
+nfsrahead_SOURCES = main.c
|
||||||
|
+nfsrahead_LDFLAGS= -lmount
|
||||||
|
+nfsrahead_LDADD = ../../support/nfs/libnfsconf.la
|
||||||
|
+
|
||||||
|
+man5_MANS = nfsrahead.man
|
||||||
|
+EXTRA_DIST = $(man5_MANS)
|
||||||
|
+
|
||||||
|
+udev_rulesdir = /usr/lib/udev/rules.d/
|
||||||
|
+udev_rules_DATA = 99-nfs.rules
|
||||||
|
+
|
||||||
|
+99-nfs.rules: 99-nfs.rules.in $(builddefs)
|
||||||
|
+ $(SED) "s|_libexecdir_|@libexecdir@|g" 99-nfs.rules.in > $@
|
||||||
|
+
|
||||||
|
+clean-local:
|
||||||
|
+ $(RM) 99-nfs.rules
|
||||||
|
diff --git a/tools/nfsrahead/main.c b/tools/nfsrahead/main.c
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..c83c6f71
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tools/nfsrahead/main.c
|
||||||
|
@@ -0,0 +1,192 @@
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
+
|
||||||
|
+#include <libmount/libmount.h>
|
||||||
|
+#include <sys/sysmacros.h>
|
||||||
|
+
|
||||||
|
+#include "xlog.h"
|
||||||
|
+#include "conffile.h"
|
||||||
|
+
|
||||||
|
+#ifndef MOUNTINFO_PATH
|
||||||
|
+#define MOUNTINFO_PATH "/proc/self/mountinfo"
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#define CONF_NAME "nfsrahead"
|
||||||
|
+#define NFS_DEFAULT_READAHEAD 128
|
||||||
|
+
|
||||||
|
+/* Device information from the system */
|
||||||
|
+struct device_info {
|
||||||
|
+ char *device_number;
|
||||||
|
+ dev_t dev;
|
||||||
|
+ char *mountpoint;
|
||||||
|
+ char *fstype;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* Convert a string in the format n:m to a device number */
|
||||||
|
+static int fill_device_number(struct device_info *info)
|
||||||
|
+{
|
||||||
|
+ char *s = strdup(info->device_number), *p;
|
||||||
|
+ char *maj_s, *min_s;
|
||||||
|
+ unsigned int maj, min;
|
||||||
|
+ int err = -EINVAL;
|
||||||
|
+
|
||||||
|
+ maj_s = p = s;
|
||||||
|
+ for ( ; *p != ':' && *p != '\0'; p++)
|
||||||
|
+ ;
|
||||||
|
+
|
||||||
|
+ if (*p == '\0')
|
||||||
|
+ goto out_free;
|
||||||
|
+
|
||||||
|
+ err = 0;
|
||||||
|
+ *p = '\0';
|
||||||
|
+ min_s = p + 1;
|
||||||
|
+
|
||||||
|
+ maj = strtol(maj_s, NULL, 10);
|
||||||
|
+ min = strtol(min_s, NULL, 10);
|
||||||
|
+
|
||||||
|
+ info->dev = makedev(maj, min);
|
||||||
|
+out_free:
|
||||||
|
+ free(s);
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#define sfree(ptr) if (ptr) free(ptr)
|
||||||
|
+
|
||||||
|
+/* device_info maintenance */
|
||||||
|
+static void init_device_info(struct device_info *di, const char *device_number)
|
||||||
|
+{
|
||||||
|
+ di->device_number = strdup(device_number);
|
||||||
|
+ di->dev = 0;
|
||||||
|
+ di->mountpoint = NULL;
|
||||||
|
+ di->fstype = NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static void free_device_info(struct device_info *di)
|
||||||
|
+{
|
||||||
|
+ sfree(di->mountpoint);
|
||||||
|
+ sfree(di->fstype);
|
||||||
|
+ sfree(di->device_number);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int get_mountinfo(const char *device_number, struct device_info *device_info, const char *mountinfo_path)
|
||||||
|
+{
|
||||||
|
+ int ret = 0;
|
||||||
|
+ struct libmnt_table *mnttbl;
|
||||||
|
+ struct libmnt_fs *fs;
|
||||||
|
+ char *target;
|
||||||
|
+
|
||||||
|
+ init_device_info(device_info, device_number);
|
||||||
|
+ if ((ret = fill_device_number(device_info)) < 0)
|
||||||
|
+ goto out_free_device_info;
|
||||||
|
+
|
||||||
|
+ mnttbl = mnt_new_table();
|
||||||
|
+
|
||||||
|
+ if ((ret = mnt_table_parse_file(mnttbl, mountinfo_path)) < 0) {
|
||||||
|
+ xlog(D_GENERAL, "Failed to parse %s\n", mountinfo_path);
|
||||||
|
+ goto out_free_tbl;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if ((fs = mnt_table_find_devno(mnttbl, device_info->dev, MNT_ITER_FORWARD)) == NULL) {
|
||||||
|
+ ret = ENOENT;
|
||||||
|
+ goto out_free_tbl;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if ((target = (char *)mnt_fs_get_target(fs)) == NULL) {
|
||||||
|
+ ret = ENOENT;
|
||||||
|
+ goto out_free_fs;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ device_info->mountpoint = strdup(target);
|
||||||
|
+ target = (char *)mnt_fs_get_fstype(fs);
|
||||||
|
+ if (target)
|
||||||
|
+ device_info->fstype = strdup(target);
|
||||||
|
+
|
||||||
|
+out_free_fs:
|
||||||
|
+ mnt_free_fs(fs);
|
||||||
|
+out_free_tbl:
|
||||||
|
+ mnt_free_table(mnttbl);
|
||||||
|
+out_free_device_info:
|
||||||
|
+ free(device_info->device_number);
|
||||||
|
+ device_info->device_number = NULL;
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int get_device_info(const char *device_number, struct device_info *device_info)
|
||||||
|
+{
|
||||||
|
+ int ret = ENOENT;
|
||||||
|
+ for (int retry_count = 0; retry_count < 10 && ret != 0; retry_count++)
|
||||||
|
+ ret = get_mountinfo(device_number, device_info, MOUNTINFO_PATH);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int conf_get_readahead(const char *kind) {
|
||||||
|
+ int readahead = 0;
|
||||||
|
+
|
||||||
|
+ if((readahead = conf_get_num(CONF_NAME, kind, -1)) == -1)
|
||||||
|
+ readahead = conf_get_num(CONF_NAME, "default", NFS_DEFAULT_READAHEAD);
|
||||||
|
+
|
||||||
|
+ return readahead;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int main(int argc, char **argv)
|
||||||
|
+{
|
||||||
|
+ int ret = 0, retry, opt;
|
||||||
|
+ struct device_info device;
|
||||||
|
+ unsigned int readahead = 128, log_level, log_stderr = 0;
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ log_level = D_ALL & ~D_GENERAL;
|
||||||
|
+ while((opt = getopt(argc, argv, "dF")) != -1) {
|
||||||
|
+ switch (opt) {
|
||||||
|
+ case 'd':
|
||||||
|
+ log_level = D_ALL;
|
||||||
|
+ break;
|
||||||
|
+ case 'F':
|
||||||
|
+ log_stderr = 1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ conf_init_file(NFS_CONFFILE);
|
||||||
|
+
|
||||||
|
+ xlog_stderr(log_stderr);
|
||||||
|
+ xlog_syslog(~log_stderr);
|
||||||
|
+ xlog_config(log_level, 1);
|
||||||
|
+ xlog_open(CONF_NAME);
|
||||||
|
+
|
||||||
|
+ // xlog_err causes the system to exit
|
||||||
|
+ if ((argc - optind) != 1)
|
||||||
|
+ xlog_err("expected the device number of a BDI; is udev ok?");
|
||||||
|
+
|
||||||
|
+ for (retry = 0; retry <= 10; retry++ )
|
||||||
|
+ if ((ret = get_device_info(argv[optind], &device)) == 0)
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ if (ret != 0) {
|
||||||
|
+ xlog(D_GENERAL, "unable to find device %s\n", argv[optind]);
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (strncmp("nfs", device.fstype, 3) != 0) {
|
||||||
|
+ xlog(D_GENERAL,
|
||||||
|
+ "not setting readahead for non supported fstype %s on device %s\n",
|
||||||
|
+ device.fstype, argv[optind]);
|
||||||
|
+ ret = -EINVAL;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ readahead = conf_get_readahead(device.fstype);
|
||||||
|
+
|
||||||
|
+ xlog(D_FAC7, "setting %s readahead to %d\n", device.mountpoint, readahead);
|
||||||
|
+
|
||||||
|
+ printf("%d\n", readahead);
|
||||||
|
+
|
||||||
|
+out:
|
||||||
|
+ free_device_info(&device);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
diff --git a/tools/nfsrahead/nfsrahead.man b/tools/nfsrahead/nfsrahead.man
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..5488f633
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tools/nfsrahead/nfsrahead.man
|
||||||
|
@@ -0,0 +1,72 @@
|
||||||
|
+.\" Manpage for nfsrahead.
|
||||||
|
+.nh
|
||||||
|
+.ad l
|
||||||
|
+.TH man 5 "08 Mar 2022" "1.0" "nfsrahead man page"
|
||||||
|
+.SH NAME
|
||||||
|
+
|
||||||
|
+nfsrahead \- Configure the readahead for NFS mounts
|
||||||
|
+
|
||||||
|
+.SH SYNOPSIS
|
||||||
|
+
|
||||||
|
+nfsrahead [-F] [-d] <device>
|
||||||
|
+
|
||||||
|
+.SH DESCRIPTION
|
||||||
|
+
|
||||||
|
+\fInfsrahead\fR is a tool intended to be used with udev to set the \fIread_ahead_kb\fR parameter of NFS mounts, according to the configuration file (see \fICONFIGURATION\fR). \fIdevice\fR is the device number for the NFS backing device as provided by the kernel.
|
||||||
|
+
|
||||||
|
+.SH OPTIONS
|
||||||
|
+.TP
|
||||||
|
+.B -F
|
||||||
|
+Send messages to
|
||||||
|
+.I stderr
|
||||||
|
+instead of
|
||||||
|
+.I syslog
|
||||||
|
+
|
||||||
|
+.TP
|
||||||
|
+.B -d
|
||||||
|
+Increase the debugging level.
|
||||||
|
+
|
||||||
|
+.SH CONFIGURATION
|
||||||
|
+.I nfsrahead
|
||||||
|
+is configured in
|
||||||
|
+.IR /etc/nfs.conf ,
|
||||||
|
+in the section titled
|
||||||
|
+.IR nfsrahead .
|
||||||
|
+It accepts the following configurations.
|
||||||
|
+
|
||||||
|
+.TP
|
||||||
|
+.B nfs=<value>
|
||||||
|
+The readahead value applied to NFSv3 mounts.
|
||||||
|
+
|
||||||
|
+.TP
|
||||||
|
+.B nfs4=<value>
|
||||||
|
+The readahead value applied to NFSv4 mounts.
|
||||||
|
+
|
||||||
|
+.TP
|
||||||
|
+.B default=<value>
|
||||||
|
+The default configuration when none of the configurations above is set.
|
||||||
|
+
|
||||||
|
+.SH EXAMPLE CONFIGURATION
|
||||||
|
+[nfsrahead]
|
||||||
|
+.br
|
||||||
|
+nfs=15000 # readahead of 15000 for NFSv3 mounts
|
||||||
|
+.br
|
||||||
|
+nfs4=16000 # readahead of 16000 for NFSv4 mounts
|
||||||
|
+.br
|
||||||
|
+default=128 # default is 128
|
||||||
|
+
|
||||||
|
+.SH SEE ALSO
|
||||||
|
+
|
||||||
|
+.BR mount.nfs (8),
|
||||||
|
+.BR nfs (5),
|
||||||
|
+.BR nfs.conf (5),
|
||||||
|
+.BR udev (7),
|
||||||
|
+.BR bcc-readahead (8)
|
||||||
|
+
|
||||||
|
+.SH BUGS
|
||||||
|
+
|
||||||
|
+No known bugs.
|
||||||
|
+
|
||||||
|
+.SH AUTHOR
|
||||||
|
+
|
||||||
|
+Thiago Rafael Becker <trbecker@gmail.com>
|
||||||
|
diff --git a/utils/nfsidmap/nfsidmap.man b/utils/nfsidmap/nfsidmap.man
|
||||||
|
index 2af16f31..1911c41b 100644
|
||||||
|
--- a/utils/nfsidmap/nfsidmap.man
|
||||||
|
+++ b/utils/nfsidmap/nfsidmap.man
|
||||||
|
@@ -2,7 +2,7 @@
|
||||||
|
.\"@(#)nfsidmap(8) - The NFS idmapper upcall program
|
||||||
|
.\"
|
||||||
|
.\" Copyright (C) 2010 Bryan Schumaker <bjschuma@netapp.com>
|
||||||
|
-.TH nfsidmap 5 "1 October 2010"
|
||||||
|
+.TH nfsidmap 8 "1 October 2010"
|
||||||
|
.SH NAME
|
||||||
|
nfsidmap \- The NFS idmapper upcall program
|
||||||
|
.SH SYNOPSIS
|
12
SOURCES/nfs-utils-2.3.3-rpcctl-posixpath.patch
Normal file
12
SOURCES/nfs-utils-2.3.3-rpcctl-posixpath.patch
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
diff -up nfs-utils-2.3.3/tools/rpcctl/rpcctl.py.orig nfs-utils-2.3.3/tools/rpcctl/rpcctl.py
|
||||||
|
--- nfs-utils-2.3.3/tools/rpcctl/rpcctl.py.orig 2022-06-27 13:22:19.844747880 -0400
|
||||||
|
+++ nfs-utils-2.3.3/tools/rpcctl/rpcctl.py 2022-06-27 13:23:02.168004219 -0400
|
||||||
|
@@ -213,7 +213,7 @@ class RpcClient:
|
||||||
|
def __init__(self, path):
|
||||||
|
self.path = path
|
||||||
|
self.name = path.stem
|
||||||
|
- self.switch = XprtSwitch(path / (path / "switch").readlink(), sep=",")
|
||||||
|
+ self.switch = XprtSwitch(path / os.readlink(path / "switch"), sep=",")
|
||||||
|
|
||||||
|
def __lt__(self, rhs):
|
||||||
|
return self.name < rhs.name
|
34
SOURCES/nfs-utils-2.3.3-rpcctl-subparser.patch
Normal file
34
SOURCES/nfs-utils-2.3.3-rpcctl-subparser.patch
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
From 2fdd10bebf395b51e931a10adbdc85f3a3f8a285 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Alice Mitchell <ajmitchell@redhat.com>
|
||||||
|
Date: Thu, 23 Jun 2022 16:04:45 +0100
|
||||||
|
Subject: [PATCH] Remove subparser required option as that was added in py3.7
|
||||||
|
|
||||||
|
---
|
||||||
|
tools/rpcctl/rpcctl.py | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/tools/rpcctl/rpcctl.py b/tools/rpcctl/rpcctl.py
|
||||||
|
index d2110ad6..2ac6ede9 100755
|
||||||
|
--- a/tools/rpcctl/rpcctl.py
|
||||||
|
+++ b/tools/rpcctl/rpcctl.py
|
||||||
|
@@ -120,7 +120,7 @@ class Xprt:
|
||||||
|
set = subparser.add_parser("set", help="Change an xprt property")
|
||||||
|
set.add_argument("xprt", metavar="XPRT", nargs=1,
|
||||||
|
help="Name of a specific xprt to modify")
|
||||||
|
- subparser = set.add_subparsers(required=True)
|
||||||
|
+ subparser = set.add_subparsers()
|
||||||
|
online = subparser.add_parser("online", help="Set an xprt online")
|
||||||
|
online.set_defaults(func=Xprt.set_property, property="online")
|
||||||
|
offline = subparser.add_parser("offline", help="Set an xprt offline")
|
||||||
|
@@ -185,7 +185,7 @@ class XprtSwitch:
|
||||||
|
set = subparser.add_parser("set", help="Change an xprt switch property")
|
||||||
|
set.add_argument("switch", metavar="SWITCH", nargs=1,
|
||||||
|
help="Name of a specific xprt switch to modify")
|
||||||
|
- subparser = set.add_subparsers(required=True)
|
||||||
|
+ subparser = set.add_subparsers()
|
||||||
|
dstaddr = subparser.add_parser("dstaddr", help="Change an xprt switch's dstaddr")
|
||||||
|
dstaddr.add_argument("newaddr", metavar="NEWADDR", nargs=1,
|
||||||
|
help="The new address for the xprt switch")
|
||||||
|
--
|
||||||
|
2.36.1
|
||||||
|
|
384
SOURCES/nfs-utils-2.3.3-rpcctl.patch
Normal file
384
SOURCES/nfs-utils-2.3.3-rpcctl.patch
Normal file
@ -0,0 +1,384 @@
|
|||||||
|
diff --git a/configure.ac b/configure.ac
|
||||||
|
index f2f2303b..6d464ac5 100644
|
||||||
|
--- a/configure.ac
|
||||||
|
+++ b/configure.ac
|
||||||
|
@@ -639,6 +639,7 @@ AC_CONFIG_FILES([
|
||||||
|
tools/rpcgen/Makefile
|
||||||
|
tools/mountstats/Makefile
|
||||||
|
tools/nfs-iostat/Makefile
|
||||||
|
+ tools/rpcctl/Makefile
|
||||||
|
tools/nfsdclnts/Makefile
|
||||||
|
tools/nfsconf/Makefile
|
||||||
|
tools/nfsdclddb/Makefile
|
||||||
|
diff --git a/tools/Makefile.am b/tools/Makefile.am
|
||||||
|
index 9b4b0803..c3feabbe 100644
|
||||||
|
--- a/tools/Makefile.am
|
||||||
|
+++ b/tools/Makefile.am
|
||||||
|
@@ -12,6 +12,6 @@ if CONFIG_NFSDCLD
|
||||||
|
OPTDIRS += nfsdclddb
|
||||||
|
endif
|
||||||
|
|
||||||
|
-SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat nfsdclnts $(OPTDIRS)
|
||||||
|
+SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat rpcctl nfsdclnts $(OPTDIRS)
|
||||||
|
|
||||||
|
MAINTAINERCLEANFILES = Makefile.in
|
||||||
|
diff --git a/tools/rpcctl/Makefile.am b/tools/rpcctl/Makefile.am
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..33fb431f
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tools/rpcctl/Makefile.am
|
||||||
|
@@ -0,0 +1,13 @@
|
||||||
|
+## Process this file with automake to produce Makefile.in
|
||||||
|
+PYTHON_FILES = rpcctl.py
|
||||||
|
+
|
||||||
|
+man8_MANS = rpcctl.man
|
||||||
|
+
|
||||||
|
+EXTRA_DIST = $(man8_MANS) $(PYTHON_FILES)
|
||||||
|
+
|
||||||
|
+all-local: $(PYTHON_FILES)
|
||||||
|
+
|
||||||
|
+install-data-hook:
|
||||||
|
+ $(INSTALL) -m 755 rpcctl.py $(DESTDIR)$(sbindir)/rpcctl
|
||||||
|
+
|
||||||
|
+MAINTAINERCLEANFILES=Makefile.in
|
||||||
|
diff --git a/tools/rpcctl/rpcctl.man b/tools/rpcctl/rpcctl.man
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..b87ba0df
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tools/rpcctl/rpcctl.man
|
||||||
|
@@ -0,0 +1,67 @@
|
||||||
|
+.\"
|
||||||
|
+.\" rpcctl(8)
|
||||||
|
+.\"
|
||||||
|
+.TH rpcctl 8 "15 Feb 2022"
|
||||||
|
+.SH NAME
|
||||||
|
+rpcctl \- Displays SunRPC connection information
|
||||||
|
+.SH SYNOPSIS
|
||||||
|
+.nf
|
||||||
|
+.BR rpcctl " [ \fB\-h \fR| \fB\-\-help \fR] { \fBclient \fR| \fBswitch \fR| \fBxprt \fR}"
|
||||||
|
+.P
|
||||||
|
+.BR "rpcctl client" " \fR[ \fB\-h \fR| \fB\-\-help \fR] { \fBshow \fR}"
|
||||||
|
+.BR "rpcctl client show " "\fR[ \fB\-h \f| \fB\-\-help \fR] [ \fIXPRT \fR]"
|
||||||
|
+.P
|
||||||
|
+.BR "rpcctl switch" " \fR[ \fB\-h \fR| \fB\-\-help \fR] { \fBset \fR| \fBshow \fR}"
|
||||||
|
+.BR "rpcctl switch set" " \fR[ \fB\-h \fR| \fB\-\-help \fR] \fISWITCH \fBdstaddr \fINEWADDR"
|
||||||
|
+.BR "rpcctl switch show" " \fR[ \fB\-h \fR| \fB\-\-help \fR] [ \fISWITCH \fR]"
|
||||||
|
+.P
|
||||||
|
+.BR "rpcctl xprt" " \fR[ \fB\-h \fR| \fB\-\-help \fR] { \fBremove \fR| \fBset \fR| \fBshow \fR}"
|
||||||
|
+.BR "rpcctl xprt remove" " \fR[ \fB\-h \fR| \fB\-\-help \fR] \fIXPRT"
|
||||||
|
+.BR "rpcctl xprt set" " \fR[ \fB\-h \fR| \fB\-\-help \fR] \fIXPRT \fR{ \fBdstaddr \fINEWADDR \fR| \fBoffline \fR| \fBonline \fR}"
|
||||||
|
+.BR "rpcctl xprt show" " \fR[ \fB\-h \fR| \fB\-\-help \fR] [ \fIXPRT \fR]"
|
||||||
|
+.fi
|
||||||
|
+.SH DESCRIPTION
|
||||||
|
+.RB "The " rpcctl " command displays information collected in the SunRPC sysfs files about the system's SunRPC objects.
|
||||||
|
+.P
|
||||||
|
+.SS rpcctl client \fR- \fBCommands operating on RPC clients
|
||||||
|
+.IP "\fBshow \fR[ \fICLIENT \fR] \fB(default)"
|
||||||
|
+Show detailed information about the RPC clients on this system.
|
||||||
|
+If \fICLIENT \fRwas provided, then only show information about a single RPC client.
|
||||||
|
+.P
|
||||||
|
+.SS rpcctl switch \fR- \fBCommands operating on groups of transports
|
||||||
|
+.IP "\fBset \fISWITCH \fBdstaddr \fINEWADDR"
|
||||||
|
+Change the destination address of all transports in the \fISWITCH \fRto \fINEWADDR\fR.
|
||||||
|
+\fINEWADDR \fRcan be an IP address, DNS name, or anything else resolvable by \fBgethostbyname\fR(3).
|
||||||
|
+.IP "\fBshow \fR[ \fISWITCH \fR] \fB(default)"
|
||||||
|
+Show detailed information about groups of transports on this system.
|
||||||
|
+If \fISWITCH \fRwas provided, then only show information about a single transport group.
|
||||||
|
+.P
|
||||||
|
+.SS rpcctl xprt \fR- \fBCommands operating on individual transports
|
||||||
|
+.IP "\fBremove \fIXPRT"
|
||||||
|
+Removes the specified \fIXPRT \fRfrom the system.
|
||||||
|
+Note that "main" transports cannot be removed.
|
||||||
|
+.P
|
||||||
|
+.IP "\fBset \fIXPRT \fBdstaddr \fINEWADDR"
|
||||||
|
+Change the destination address of the specified \fIXPRT \fR to \fINEWADDR\fR.
|
||||||
|
+\fINEWADDR \fRcan be an IP address, DNS name, or anything else resolvable by \fBgethostbyname\fR(3).
|
||||||
|
+.P
|
||||||
|
+.IP "\fBset \fIXPRT \fBoffline"
|
||||||
|
+Sets the specified \fIXPRT\fR's state to offline.
|
||||||
|
+.P
|
||||||
|
+.IP "\fBset \fIXPRT \fBonline"
|
||||||
|
+Sets the specified \fIXPRT\fR's state to online.
|
||||||
|
+.IP "\fBshow \fR[ \fIXPRT \fR] \fB(default)"
|
||||||
|
+Show detailed information about this system's transports.
|
||||||
|
+If \fIXPRT \fRwas provided, then only show information about a single transport.
|
||||||
|
+.SH EXAMPLES
|
||||||
|
+.IP "\fBrpcctl switch show switch-2"
|
||||||
|
+Show details about the RPC switch named "switch-2".
|
||||||
|
+.IP "\fBrpcctl xprt remove xprt-4"
|
||||||
|
+Remove the xprt named "xprt-4" from the system.
|
||||||
|
+.IP "\fBrpcctl xprt set xprt-3 dstaddr https://linux-nfs.org
|
||||||
|
+Change the dstaddr of the xprt named "xprt-3" to point to linux-nfs.org
|
||||||
|
+.SH DIRECTORY
|
||||||
|
+.TP
|
||||||
|
+.B /sys/kernel/sunrpc/
|
||||||
|
+.SH AUTHOR
|
||||||
|
+Anna Schumaker <Anna.Schumaker@Netapp.com>
|
||||||
|
diff --git a/tools/rpcctl/rpcctl.py b/tools/rpcctl/rpcctl.py
|
||||||
|
new file mode 100755
|
||||||
|
index 00000000..d2110ad6
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tools/rpcctl/rpcctl.py
|
||||||
|
@@ -0,0 +1,262 @@
|
||||||
|
+#!/usr/bin/python3
|
||||||
|
+import argparse
|
||||||
|
+import collections
|
||||||
|
+import errno
|
||||||
|
+import os
|
||||||
|
+import pathlib
|
||||||
|
+import socket
|
||||||
|
+import sys
|
||||||
|
+
|
||||||
|
+with open("/proc/mounts", 'r') as f:
|
||||||
|
+ mount = [ line.split()[1] for line in f if "sysfs" in line ]
|
||||||
|
+ if len(mount) == 0:
|
||||||
|
+ print("ERROR: sysfs is not mounted")
|
||||||
|
+ sys.exit(1)
|
||||||
|
+
|
||||||
|
+sunrpc = pathlib.Path(mount[0]) / "kernel" / "sunrpc"
|
||||||
|
+if not sunrpc.is_dir():
|
||||||
|
+ print("ERROR: sysfs does not have sunrpc directory")
|
||||||
|
+ sys.exit(1)
|
||||||
|
+
|
||||||
|
+def read_addr_file(path):
|
||||||
|
+ try:
|
||||||
|
+ with open(path, 'r') as f:
|
||||||
|
+ return f.readline().strip()
|
||||||
|
+ except:
|
||||||
|
+ return "(enoent)"
|
||||||
|
+
|
||||||
|
+def write_addr_file(path, newaddr):
|
||||||
|
+ with open(path, 'w') as f:
|
||||||
|
+ f.write(newaddr)
|
||||||
|
+ return read_addr_file(path)
|
||||||
|
+
|
||||||
|
+def read_info_file(path):
|
||||||
|
+ res = collections.defaultdict(int)
|
||||||
|
+ try:
|
||||||
|
+ with open(path) as info:
|
||||||
|
+ lines = [ l.split("=", 1) for l in info if "=" in l ]
|
||||||
|
+ res.update({ key:int(val.strip()) for (key, val) in lines })
|
||||||
|
+ finally:
|
||||||
|
+ return res
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class Xprt:
|
||||||
|
+ def __init__(self, path):
|
||||||
|
+ self.path = path
|
||||||
|
+ self.name = path.stem.rsplit("-", 1)[0]
|
||||||
|
+ self.type = path.stem.split("-")[2]
|
||||||
|
+ self.info = read_info_file(path / "xprt_info")
|
||||||
|
+ self.dstaddr = read_addr_file(path / "dstaddr")
|
||||||
|
+ self.srcaddr = read_addr_file(path / "srcaddr")
|
||||||
|
+ self.read_state()
|
||||||
|
+
|
||||||
|
+ def __lt__(self, rhs):
|
||||||
|
+ return self.name < rhs.name
|
||||||
|
+
|
||||||
|
+ def _xprt(self):
|
||||||
|
+ main = ", main" if self.info.get("main_xprt") else ""
|
||||||
|
+ return f"{self.name}: {self.type}, {self.dstaddr}, " \
|
||||||
|
+ f"port {self.info['dst_port']}, state <{self.state}>{main}"
|
||||||
|
+
|
||||||
|
+ def _src_reqs(self):
|
||||||
|
+ return f" Source: {self.srcaddr}, port {self.info['src_port']}, " \
|
||||||
|
+ f"Requests: {self.info['num_reqs']}"
|
||||||
|
+
|
||||||
|
+ def _cong_slots(self):
|
||||||
|
+ return f" Congestion: cur {self.info['cur_cong']}, win {self.info['cong_win']}, " \
|
||||||
|
+ f"Slots: min {self.info['min_num_slots']}, max {self.info['max_num_slots']}"
|
||||||
|
+
|
||||||
|
+ def _queues(self):
|
||||||
|
+ return f" Queues: binding {self.info['binding_q_len']}, " \
|
||||||
|
+ f"sending {self.info['sending_q_len']}, pending {self.info['pending_q_len']}, " \
|
||||||
|
+ f"backlog {self.info['backlog_q_len']}, tasks {self.info['tasks_queuelen']}"
|
||||||
|
+
|
||||||
|
+ def __str__(self):
|
||||||
|
+ if not self.path.exists():
|
||||||
|
+ return f"{self.name}: has been removed"
|
||||||
|
+ return "\n".join([self._xprt(), self._src_reqs(),
|
||||||
|
+ self._cong_slots(), self._queues() ])
|
||||||
|
+
|
||||||
|
+ def read_state(self):
|
||||||
|
+ if self.path.exists():
|
||||||
|
+ with open(self.path / "xprt_state") as f:
|
||||||
|
+ self.state = ','.join(f.readline().split()[1:])
|
||||||
|
+
|
||||||
|
+ def small_str(self):
|
||||||
|
+ main = " [main]" if self.info.get("main_xprt") else ""
|
||||||
|
+ return f"{self.name}: {self.type}, {self.dstaddr}{main}"
|
||||||
|
+
|
||||||
|
+ def set_dstaddr(self, newaddr):
|
||||||
|
+ self.dstaddr = write_addr_file(self.path / "dstaddr", newaddr)
|
||||||
|
+
|
||||||
|
+ def set_state(self, state):
|
||||||
|
+ if self.info.get("main_xprt"):
|
||||||
|
+ raise Exception(f"Main xprts cannot be set {state}")
|
||||||
|
+ with open(self.path / "xprt_state", 'w') as f:
|
||||||
|
+ f.write(state)
|
||||||
|
+ self.read_state()
|
||||||
|
+
|
||||||
|
+ def remove(self):
|
||||||
|
+ if self.info.get("main_xprt"):
|
||||||
|
+ raise Exception("Main xprts cannot be removed")
|
||||||
|
+ self.set_state("offline")
|
||||||
|
+ self.set_state("remove")
|
||||||
|
+
|
||||||
|
+ def add_command(subparser):
|
||||||
|
+ parser = subparser.add_parser("xprt", help="Commands for individual xprts")
|
||||||
|
+ parser.set_defaults(func=Xprt.show, xprt=None)
|
||||||
|
+ subparser = parser.add_subparsers()
|
||||||
|
+
|
||||||
|
+ remove = subparser.add_parser("remove", help="Remove an xprt")
|
||||||
|
+ remove.add_argument("xprt", metavar="XPRT", nargs=1,
|
||||||
|
+ help="Name of the xprt to remove")
|
||||||
|
+ remove.set_defaults(func=Xprt.set_property, property="remove")
|
||||||
|
+
|
||||||
|
+ show = subparser.add_parser("show", help="Show xprts")
|
||||||
|
+ show.add_argument("xprt", metavar="XPRT", nargs='?',
|
||||||
|
+ help="Name of a specific xprt to show")
|
||||||
|
+ show.set_defaults(func=Xprt.show)
|
||||||
|
+
|
||||||
|
+ set = subparser.add_parser("set", help="Change an xprt property")
|
||||||
|
+ set.add_argument("xprt", metavar="XPRT", nargs=1,
|
||||||
|
+ help="Name of a specific xprt to modify")
|
||||||
|
+ subparser = set.add_subparsers(required=True)
|
||||||
|
+ online = subparser.add_parser("online", help="Set an xprt online")
|
||||||
|
+ online.set_defaults(func=Xprt.set_property, property="online")
|
||||||
|
+ offline = subparser.add_parser("offline", help="Set an xprt offline")
|
||||||
|
+ offline.set_defaults(func=Xprt.set_property, property="offline")
|
||||||
|
+ dstaddr = subparser.add_parser("dstaddr", help="Change an xprt's dstaddr")
|
||||||
|
+ dstaddr.add_argument("newaddr", metavar="NEWADDR", nargs=1,
|
||||||
|
+ help="The new address for the xprt")
|
||||||
|
+ dstaddr.set_defaults(func=Xprt.set_property, property="dstaddr")
|
||||||
|
+
|
||||||
|
+ def get_by_name(name):
|
||||||
|
+ glob = f"**/{name}-*" if name else "**/xprt-*"
|
||||||
|
+ res = [ Xprt(x) for x in (sunrpc / "xprt-switches").glob(glob) ]
|
||||||
|
+ if name and len(res) == 0:
|
||||||
|
+ raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT),
|
||||||
|
+ f"{sunrpc / 'xprt-switches' / glob}")
|
||||||
|
+ return sorted(res)
|
||||||
|
+
|
||||||
|
+ def show(args):
|
||||||
|
+ for xprt in Xprt.get_by_name(args.xprt):
|
||||||
|
+ print(xprt)
|
||||||
|
+
|
||||||
|
+ def set_property(args):
|
||||||
|
+ for xprt in Xprt.get_by_name(args.xprt[0]):
|
||||||
|
+ if args.property == "dstaddr":
|
||||||
|
+ xprt.set_dstaddr(socket.gethostbyname(args.newaddr[0]))
|
||||||
|
+ elif args.property == "remove":
|
||||||
|
+ xprt.remove()
|
||||||
|
+ else:
|
||||||
|
+ xprt.set_state(args.property)
|
||||||
|
+ print(xprt)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class XprtSwitch:
|
||||||
|
+ def __init__(self, path, sep=":"):
|
||||||
|
+ self.path = path
|
||||||
|
+ self.name = path.stem
|
||||||
|
+ self.info = read_info_file(path / "xprt_switch_info")
|
||||||
|
+ self.xprts = sorted([ Xprt(p) for p in self.path.iterdir() if p.is_dir() ])
|
||||||
|
+ self.sep = sep
|
||||||
|
+
|
||||||
|
+ def __lt__(self, rhs):
|
||||||
|
+ return self.name < rhs.name
|
||||||
|
+
|
||||||
|
+ def __str__(self):
|
||||||
|
+ switch = f"{self.name}{self.sep} " \
|
||||||
|
+ f"xprts {self.info['num_xprts']}, " \
|
||||||
|
+ f"active {self.info['num_active']}, " \
|
||||||
|
+ f"queue {self.info['queue_len']}"
|
||||||
|
+ xprts = [ f" {x.small_str()}" for x in self.xprts ]
|
||||||
|
+ return "\n".join([ switch ] + xprts)
|
||||||
|
+
|
||||||
|
+ def add_command(subparser):
|
||||||
|
+ parser = subparser.add_parser("switch", help="Commands for xprt switches")
|
||||||
|
+ parser.set_defaults(func=XprtSwitch.show, switch=None)
|
||||||
|
+ subparser = parser.add_subparsers()
|
||||||
|
+
|
||||||
|
+ show = subparser.add_parser("show", help="Show xprt switches")
|
||||||
|
+ show.add_argument("switch", metavar="SWITCH", nargs='?',
|
||||||
|
+ help="Name of a specific switch to show")
|
||||||
|
+ show.set_defaults(func=XprtSwitch.show)
|
||||||
|
+
|
||||||
|
+ set = subparser.add_parser("set", help="Change an xprt switch property")
|
||||||
|
+ set.add_argument("switch", metavar="SWITCH", nargs=1,
|
||||||
|
+ help="Name of a specific xprt switch to modify")
|
||||||
|
+ subparser = set.add_subparsers(required=True)
|
||||||
|
+ dstaddr = subparser.add_parser("dstaddr", help="Change an xprt switch's dstaddr")
|
||||||
|
+ dstaddr.add_argument("newaddr", metavar="NEWADDR", nargs=1,
|
||||||
|
+ help="The new address for the xprt switch")
|
||||||
|
+ dstaddr.set_defaults(func=XprtSwitch.set_property, property="dstaddr")
|
||||||
|
+
|
||||||
|
+ def get_by_name(name):
|
||||||
|
+ xprt_switches = sunrpc / "xprt-switches"
|
||||||
|
+ if name:
|
||||||
|
+ return [ XprtSwitch(xprt_switches / name) ]
|
||||||
|
+ return [ XprtSwitch(f) for f in sorted(xprt_switches.iterdir()) ]
|
||||||
|
+
|
||||||
|
+ def show(args):
|
||||||
|
+ for switch in XprtSwitch.get_by_name(args.switch):
|
||||||
|
+ print(switch)
|
||||||
|
+
|
||||||
|
+ def set_property(args):
|
||||||
|
+ for switch in XprtSwitch.get_by_name(args.switch[0]):
|
||||||
|
+ resolved = socket.gethostbyname(args.newaddr[0])
|
||||||
|
+ for xprt in switch.xprts:
|
||||||
|
+ xprt.set_dstaddr(resolved)
|
||||||
|
+ print(switch)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class RpcClient:
|
||||||
|
+ def __init__(self, path):
|
||||||
|
+ self.path = path
|
||||||
|
+ self.name = path.stem
|
||||||
|
+ self.switch = XprtSwitch(path / (path / "switch").readlink(), sep=",")
|
||||||
|
+
|
||||||
|
+ def __lt__(self, rhs):
|
||||||
|
+ return self.name < rhs.name
|
||||||
|
+
|
||||||
|
+ def __str__(self):
|
||||||
|
+ return f"{self.name}: {self.switch}"
|
||||||
|
+
|
||||||
|
+ def add_command(subparser):
|
||||||
|
+ parser = subparser.add_parser("client", help="Commands for rpc clients")
|
||||||
|
+ parser.set_defaults(func=RpcClient.show, client=None)
|
||||||
|
+ subparser = parser.add_subparsers()
|
||||||
|
+
|
||||||
|
+ show = subparser.add_parser("show", help="Show rpc clients")
|
||||||
|
+ show.add_argument("client", metavar="CLIENT", nargs='?',
|
||||||
|
+ help="Name of a specific rpc client to show")
|
||||||
|
+ parser.set_defaults(func=RpcClient.show)
|
||||||
|
+
|
||||||
|
+ def get_by_name(name):
|
||||||
|
+ rpc_clients = sunrpc / "rpc-clients"
|
||||||
|
+ if name:
|
||||||
|
+ return [ RpcClient(rpc_clients / name) ]
|
||||||
|
+ return [ RpcClient(f) for f in sorted(rpc_clients.iterdir()) ]
|
||||||
|
+
|
||||||
|
+ def show(args):
|
||||||
|
+ for client in RpcClient.get_by_name(args.client):
|
||||||
|
+ print(client)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+parser = argparse.ArgumentParser()
|
||||||
|
+
|
||||||
|
+def show_small_help(args):
|
||||||
|
+ parser.print_usage()
|
||||||
|
+ print("sunrpc dir:", sunrpc)
|
||||||
|
+parser.set_defaults(func=show_small_help)
|
||||||
|
+
|
||||||
|
+subparser = parser.add_subparsers(title="commands")
|
||||||
|
+RpcClient.add_command(subparser)
|
||||||
|
+XprtSwitch.add_command(subparser)
|
||||||
|
+Xprt.add_command(subparser)
|
||||||
|
+
|
||||||
|
+args = parser.parse_args()
|
||||||
|
+try:
|
||||||
|
+ args.func(args)
|
||||||
|
+except Exception as e:
|
||||||
|
+ print(str(e))
|
||||||
|
+ sys.exit(1)
|
37
SOURCES/nfs-utils-2.3.3-systemd-exportfs-nofail.patch
Normal file
37
SOURCES/nfs-utils-2.3.3-systemd-exportfs-nofail.patch
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
commit 003000d451833309c963054e58a48fa1df7e767b
|
||||||
|
Author: Steve Dickson <steved@redhat.com>
|
||||||
|
Date: Thu Dec 10 13:13:03 2020 -0500
|
||||||
|
|
||||||
|
exportfs: Ingnore export failures in nfs-server.serivce unit
|
||||||
|
|
||||||
|
With some recent commits, exportfs will continue on trying to
|
||||||
|
export filesystems even when an entry is invalid or does
|
||||||
|
not exist, but will still have a non-zero exit to report
|
||||||
|
the error.
|
||||||
|
|
||||||
|
This situation should not stop the nfs-server service
|
||||||
|
from comingup so nfs-server.service file should
|
||||||
|
ignore these types of failures
|
||||||
|
|
||||||
|
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/systemd/nfs-server.service b/systemd/nfs-server.service
|
||||||
|
index 06c1adb7..b432f910 100644
|
||||||
|
--- a/systemd/nfs-server.service
|
||||||
|
+++ b/systemd/nfs-server.service
|
||||||
|
@@ -21,13 +21,13 @@ After=rpc-gssd.service gssproxy.service rpc-svcgssd.service
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
RemainAfterExit=yes
|
||||||
|
-ExecStartPre=/usr/sbin/exportfs -r
|
||||||
|
+ExecStartPre=-/usr/sbin/exportfs -r
|
||||||
|
ExecStart=/usr/sbin/rpc.nfsd
|
||||||
|
ExecStop=/usr/sbin/rpc.nfsd 0
|
||||||
|
ExecStopPost=/usr/sbin/exportfs -au
|
||||||
|
ExecStopPost=/usr/sbin/exportfs -f
|
||||||
|
|
||||||
|
-ExecReload=/usr/sbin/exportfs -r
|
||||||
|
+ExecReload=-/usr/sbin/exportfs -r
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
13
SOURCES/nfs-utils-2.3.3-systemd-rpcstatd.patch
Normal file
13
SOURCES/nfs-utils-2.3.3-systemd-rpcstatd.patch
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
diff -up nfs-utils-2.3.3/systemd/rpc-statd.service.orig nfs-utils-2.3.3/systemd/rpc-statd.service
|
||||||
|
--- nfs-utils-2.3.3/systemd/rpc-statd.service.orig 2018-09-06 14:09:08.000000000 -0400
|
||||||
|
+++ nfs-utils-2.3.3/systemd/rpc-statd.service 2022-08-02 11:02:44.327397404 -0400
|
||||||
|
@@ -4,7 +4,8 @@ DefaultDependencies=no
|
||||||
|
Conflicts=umount.target
|
||||||
|
Requires=nss-lookup.target rpcbind.socket
|
||||||
|
Wants=network-online.target
|
||||||
|
-After=network-online.target nss-lookup.target rpcbind.socket
|
||||||
|
+Wants=rpc-statd-notify.service
|
||||||
|
+After=network-online.target nss-lookup.target rpcbind.service
|
||||||
|
|
||||||
|
PartOf=nfs-utils.service
|
||||||
|
|
@ -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: 31%{?dist}
|
Release: 64%{?dist}
|
||||||
Epoch: 1
|
Epoch: 1
|
||||||
|
|
||||||
# group all 32bit related archs
|
# group all 32bit related archs
|
||||||
@ -52,9 +52,76 @@ Patch022: nfs-utils-2.3.3-gssd-early-daemon.patch
|
|||||||
Patch023: nfs-utils-2.3.3-covscan-rm-deadcode-leaks.patch
|
Patch023: nfs-utils-2.3.3-covscan-rm-deadcode-leaks.patch
|
||||||
Patch024: nfs-utils-2.3.3-gssd-memoryleak.patch
|
Patch024: nfs-utils-2.3.3-gssd-memoryleak.patch
|
||||||
|
|
||||||
|
#
|
||||||
|
# RHEL 8.3
|
||||||
|
#
|
||||||
|
Patch025: nfs-utils-2.3.3-junction-err-fix.patch
|
||||||
|
Patch026: nfs-utils-2.3.3-nfsdcld-upstream-update.patch
|
||||||
|
Patch027: nfs-utils-2.3.3-nconnect-manpage.patch
|
||||||
|
Patch028: nfs-utils-2.3.3-nfsdclddb-rename.patch
|
||||||
|
Patch029: nfs-utils-2.3.3-nfsclnts-cmd.patch
|
||||||
|
|
||||||
|
#
|
||||||
|
# RHEL 8.4
|
||||||
|
#
|
||||||
|
Patch030: nfs-utils-2.3.3-exportfs-man-labels.patch
|
||||||
|
Patch031: nfs-utils-2.3.3-nfsiostat-div-zero.patch
|
||||||
|
Patch032: nfs-utils-2.3.3-nfsiostat-key-error.patch
|
||||||
|
Patch033: nfs-utils-2.3.3-nfsdclddb-manpage-rename.patch
|
||||||
|
Patch034: nfs-utils-2.3.3-systemd-exportfs-nofail.patch
|
||||||
|
Patch035: nfs-utils-2.3.3-exports-manpage-outdated.patch
|
||||||
|
Patch036: nfs-utils-2.3.3-gssd-multithread-updates.patch
|
||||||
|
Patch037: nfs-utils-2.3.3-mountd-pseudofs.patch
|
||||||
|
|
||||||
|
#
|
||||||
|
# RHEL 8.5
|
||||||
|
#
|
||||||
|
Patch038: nfs-utils-2.3.3-gssd-k5identity.patch
|
||||||
|
Patch039: nfs-utils-2.3.3-gssd-man-tflag.patch
|
||||||
|
Patch040: nfs-utils-2.3.3-exportfs-root.patch
|
||||||
|
Patch041: nfs-utils-2.3.3-mount-sloppy.patch
|
||||||
|
Patch042: nfs-utils-2.3.3-gssd-failed-thread.patch
|
||||||
|
Patch043: nfs-utils-2.3.3-gssd-timeout-thread.patch
|
||||||
|
Patch044: nfs-utils-2.3.3-gssd-debug-cleanup.patch
|
||||||
|
Patch045: nfs-utils-2.3.3-gssd-mutex-refcnt.patch
|
||||||
|
|
||||||
|
#
|
||||||
|
# RHEL 8.6
|
||||||
|
#
|
||||||
|
Patch046: nfs-utils-2.3.3-mountd-v4-logging.patch
|
||||||
|
Patch047: nfs-utils-2.3.3-gssd-printerr.patch
|
||||||
|
Patch048: nfs-utils-2.3.3-mount-ebusy.patch
|
||||||
|
Patch049: nfs-utils-2.3.3-nfsidmap-debug.patch
|
||||||
|
|
||||||
|
#
|
||||||
|
# RHEL 8.7
|
||||||
|
#
|
||||||
|
Patch050: nfs-utils-2.3.3-nfsman-softreval.patch
|
||||||
|
Patch051: nfs-utils-2.3.3-rpcctl.patch
|
||||||
|
Patch052: nfs-utils-2.3.3-nfsrahead.patch
|
||||||
|
Patch053: nfs-utils-2.3.3-rpcctl-subparser.patch
|
||||||
|
Patch054: nfs-utils-2.3.3-rpcctl-posixpath.patch
|
||||||
|
Patch055: nfs-utils-2.3.3-systemd-rpcstatd.patch
|
||||||
|
|
||||||
|
#
|
||||||
|
# rhel 8.8
|
||||||
|
#
|
||||||
|
Patch056: nfs-utils-2.3.3-mountd-v4clnts.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-1.2.5-idmap-errmsg.patch
|
Patch102: nfs-utils-2.3.3-idmap-errmsg.patch
|
||||||
Patch103: nfs-utils-2.3.1-systemd-gssproxy-restart.patch
|
Patch103: nfs-utils-2.3.1-systemd-gssproxy-restart.patch
|
||||||
Patch104: nfs-utils-2.3.1-systemd-svcgssd-removed.patch
|
Patch104: nfs-utils-2.3.1-systemd-svcgssd-removed.patch
|
||||||
|
|
||||||
@ -76,7 +143,7 @@ Provides: start-statd = %{epoch}:%{version}-%{release}
|
|||||||
|
|
||||||
License: MIT and GPLv2 and GPLv2+ and BSD
|
License: MIT and GPLv2 and GPLv2+ and BSD
|
||||||
Requires: rpcbind, sed, gawk, grep
|
Requires: rpcbind, sed, gawk, grep
|
||||||
Requires: kmod, keyutils, quota
|
Requires: kmod, keyutils, quota, python3-pyyaml
|
||||||
BuildRequires: libevent-devel libcap-devel
|
BuildRequires: libevent-devel libcap-devel
|
||||||
BuildRequires: libtirpc-devel libblkid-devel
|
BuildRequires: libtirpc-devel libblkid-devel
|
||||||
BuildRequires: krb5-libs >= 1.4 autoconf >= 2.57 openldap-devel >= 2.2
|
BuildRequires: krb5-libs >= 1.4 autoconf >= 2.57 openldap-devel >= 2.2
|
||||||
@ -119,16 +186,8 @@ developing programs which use the libnfsidmap library.
|
|||||||
|
|
||||||
|
|
||||||
%description
|
%description
|
||||||
The nfs-utils package provides a daemon for the kernel NFS server and
|
The nfs-utils package provides various utilities for use with NFS
|
||||||
related tools, which provides a much higher level of performance than the
|
clients and servers.
|
||||||
traditional Linux NFS server used by most users.
|
|
||||||
|
|
||||||
This package also contains the showmount program. Showmount queries the
|
|
||||||
mount daemon on a remote host for information about the NFS (Network File
|
|
||||||
System) server on the remote host. For example, showmount can display the
|
|
||||||
clients which are mounted on that host.
|
|
||||||
|
|
||||||
This package also contains the mount.nfs and umount.nfs program.
|
|
||||||
|
|
||||||
%prep
|
%prep
|
||||||
%autosetup -p1
|
%autosetup -p1
|
||||||
@ -214,8 +273,6 @@ done
|
|||||||
cat /etc/group | cut -d':' -f 1 | grep --quiet rpcuser 2>/dev/null
|
cat /etc/group | cut -d':' -f 1 | grep --quiet rpcuser 2>/dev/null
|
||||||
if [ "$?" -eq 1 ]; then
|
if [ "$?" -eq 1 ]; then
|
||||||
/usr/sbin/groupadd -g %{rpcuser_uid} rpcuser >/dev/null 2>&1 || :
|
/usr/sbin/groupadd -g %{rpcuser_uid} rpcuser >/dev/null 2>&1 || :
|
||||||
else
|
|
||||||
/usr/sbin/groupmod -g %{rpcuser_uid} rpcuser >/dev/null 2>&1 || :
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Create rpcuser uid as long as it does not already exist.
|
# Create rpcuser uid as long as it does not already exist.
|
||||||
@ -244,11 +301,6 @@ if [ $? -eq 1 ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
%post
|
%post
|
||||||
|
|
||||||
# Enable nfs-convert so if an old configuration
|
|
||||||
# exists a conversion will occur
|
|
||||||
/bin/systemctl enable nfs-convert >/dev/null 2>&1 || :
|
|
||||||
|
|
||||||
if [ $1 -eq 1 ] ; then
|
if [ $1 -eq 1 ] ; then
|
||||||
# Initial installation
|
# Initial installation
|
||||||
/bin/systemctl enable nfs-client.target >/dev/null 2>&1 || :
|
/bin/systemctl enable nfs-client.target >/dev/null 2>&1 || :
|
||||||
@ -261,8 +313,6 @@ if [ $1 -eq 0 ]; then
|
|||||||
%systemd_preun nfs-client.target
|
%systemd_preun nfs-client.target
|
||||||
%systemd_preun nfs-server.server
|
%systemd_preun nfs-server.server
|
||||||
|
|
||||||
rm -rf /var/lib/nfs/statd
|
|
||||||
rm -rf /var/lib/nfs/v4recovery
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
%postun
|
%postun
|
||||||
@ -271,6 +321,11 @@ fi
|
|||||||
|
|
||||||
/bin/systemctl --system daemon-reload >/dev/null 2>&1 || :
|
/bin/systemctl --system daemon-reload >/dev/null 2>&1 || :
|
||||||
|
|
||||||
|
if [ $1 -eq 0 ] ; then
|
||||||
|
rm -rf /var/lib/nfs/statd
|
||||||
|
rm -rf /var/lib/nfs/v4recovery
|
||||||
|
fi
|
||||||
|
|
||||||
%triggerin -- nfs-utils > 1:2.1.1-3
|
%triggerin -- nfs-utils > 1:2.1.1-3
|
||||||
/bin/systemctl try-restart gssproxy || :
|
/bin/systemctl try-restart gssproxy || :
|
||||||
|
|
||||||
@ -312,6 +367,12 @@ fi
|
|||||||
%{_sbindir}/nfsconf
|
%{_sbindir}/nfsconf
|
||||||
%{_sbindir}/nfsref
|
%{_sbindir}/nfsref
|
||||||
%{_sbindir}/nfsconvert
|
%{_sbindir}/nfsconvert
|
||||||
|
%{_sbindir}/nfsdclddb
|
||||||
|
%{_sbindir}/nfsdcld
|
||||||
|
%{_sbindir}/nfsdclnts
|
||||||
|
%{_sbindir}/rpcctl
|
||||||
|
%{_libexecdir}/nfsrahead
|
||||||
|
%{_udevrulesdir}/99-nfs.rules
|
||||||
%{_mandir}/*/*
|
%{_mandir}/*/*
|
||||||
%{_pkgdir}/*/*
|
%{_pkgdir}/*/*
|
||||||
|
|
||||||
@ -335,6 +396,119 @@ 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
|
||||||
|
- Covscan Scan: Wrong Check of Return Value (bz 2151966)
|
||||||
|
- Covscan Scan: Clang (experimental) (bz 2151971)
|
||||||
|
|
||||||
|
* Mon Sep 26 2022 Steve Dickson <steved@redhat.com> 2.3.3-58
|
||||||
|
- mountd: Check 'nfsd/clients' directory presence (bz 2123073)
|
||||||
|
|
||||||
|
* Tue Aug 2 2022 Steve Dickson <steved@redhat.com> 2.3.3-57
|
||||||
|
- rpc-statd.service: Stop rpcbind and rpc.stat in an exit race (bz 2100395)
|
||||||
|
|
||||||
|
* Thu Jun 30 2022 Steve Dickson <steved@redhat.com> 2.3.3-56
|
||||||
|
- rpcctl: 'PosixPath' object has no attribute 'readlink' (bz 2087187)
|
||||||
|
|
||||||
|
* Mon Jun 27 2022 Steve Dickson <steved@redhat.com> 2.3.3-55
|
||||||
|
- rpcctl: Remove subparser required option as that was added in py3.7 (bz 2087187)
|
||||||
|
|
||||||
|
* Tue Jun 14 2022 Steve Dickson <steved@redhat.com> 2.3.3-54
|
||||||
|
- Create the nfsrahead command (bz 1946283)
|
||||||
|
|
||||||
|
* Tue May 31 2022 Steve Dickson <steved@redhat.com> 2.3.3-53
|
||||||
|
- rpcctl: Add a rpcctl.py tool (bz 2087187)
|
||||||
|
|
||||||
|
* Tue May 24 2022 Steve Dickson <steved@redhat.com> 2.3.3-52
|
||||||
|
- manpage: Add a description of the softreval/nosoftreval (bz 2073476)
|
||||||
|
|
||||||
|
* Mon Mar 7 2022 Steve Dickson <steved@redhat.com> 2.3.3-51
|
||||||
|
- libnfsidmap: Turn off default verbosity (bz 2057612)
|
||||||
|
|
||||||
|
* Sat Feb 19 2022 Steve Dickson <steved@redhat.com> 2.3.3-50
|
||||||
|
- mount.nfs: Fix Typo auto negotiating code. (bz 1946346)
|
||||||
|
|
||||||
|
* Mon Feb 14 2022 Steve Dickson <steved@redhat.com> 2.3.3-49
|
||||||
|
- mount.nfs Fix error reporting for already mounted shares (bz 1946346)
|
||||||
|
|
||||||
|
* Thu Nov 4 2021 Steve Dickson <steved@redhat.com> 2.3.3-48
|
||||||
|
- gssd: fix crash in debug message (bz 1988283)
|
||||||
|
|
||||||
|
* Tue Nov 2 2021 Steve Dickson <steved@redhat.com> 2.3.3-47
|
||||||
|
- Enable logging for NFSv4 mount requests (bz 2004151)
|
||||||
|
|
||||||
|
* Wed Jul 28 2021 Steve Dickson <steved@redhat.com> 2.3.3-46
|
||||||
|
- mount.nfs: Fix the sloppy option processing (bz 1967883)
|
||||||
|
|
||||||
|
* Thu Jul 22 2021 Steve Dickson <steved@redhat.com> 2.3.3-45
|
||||||
|
- gssd: use mutex to protect decrement of refcount (bz 1511706)
|
||||||
|
|
||||||
|
* Mon Jul 19 2021 Steve Dickson <steved@redhat.com> 2.3.3-44
|
||||||
|
- gssd: Deal with failed thread creation (bz 1981400)
|
||||||
|
- gssd: Add timeout for upcall threads (bz 1981403)
|
||||||
|
- gssd: Cleaned up debug messages (bz 1961056)
|
||||||
|
- spec: Updated description of the nfs-utils rpm (bz 1981419)
|
||||||
|
|
||||||
|
* Sat Jul 10 2021 Steve Dickson <steved@redhat.com> 2.3.3-43
|
||||||
|
- mount.nfs: insert 'sloppy' at beginning of the options (bz 1967883)
|
||||||
|
|
||||||
|
* Mon May 10 2021 Steve Dickson <steved@redhat.com> 2.3.3-42
|
||||||
|
- gssd: Add options to allow for the use of ~/.k5identity file (bz 1868087)
|
||||||
|
- man: Correct gssd(8) description of rpc-timeout and context-timeout (bz 1908232)
|
||||||
|
- exportfs: fix unexporting of '/' (bz 1944119)
|
||||||
|
|
||||||
|
* Wed Jan 20 2021 Steve Dickson <steved@redhat.com> 2.3.3-41
|
||||||
|
- mountd: never root squash on the pseudofs (bz 1804912)
|
||||||
|
|
||||||
|
* Mon Dec 14 2020 Steve Dickson <steved@redhat.com> 2.3.3-40
|
||||||
|
- gssd: upstream multithreaded updates (bz 1906792)
|
||||||
|
|
||||||
|
* Fri Dec 11 2020 Steve Dickson <steved@redhat.com> 2.3.3-39
|
||||||
|
- systemd: Ingnore export failures in nfs-server.serivce unit (bz 1894873)
|
||||||
|
- exports.man: Remove some outdated verbiage (bz 1769688)
|
||||||
|
|
||||||
|
* Thu Dec 10 2020 Steve Dickson <steved@redhat.com> 2.3.3-38
|
||||||
|
- exports man page: warn about subdirectory exports (bz 1652437)
|
||||||
|
- Don't modify /etc/group on upgrades (bz 1856881)
|
||||||
|
- nfs-iostat: divide by zero with fresh mount (bz 1861823)
|
||||||
|
- nfsiostat: Drop autofs entries before calling compare_iostats() (bz 1859130)
|
||||||
|
- nfsdclddb: clddb-tool was recently renamed to nfsdclddb (bz 1893599)
|
||||||
|
|
||||||
|
* Thu Dec 10 2020 Alice Mitchell <ajmitchell@redhat.com> 2.3.3-37
|
||||||
|
- Remove manual enabling of nfs-convert (bz 1683895)
|
||||||
|
|
||||||
|
* Fri Oct 9 2020 Alice Mitchell <ajmitchell@redhat.com> 2.3.3-36
|
||||||
|
- Fix uninstall warnings (bz 1733170)
|
||||||
|
|
||||||
|
* Wed Jun 10 2020 Steve Dickson <steved@redhat.com> 2.3.3-35
|
||||||
|
- Fix dependency problems with nfsdclnts (bz 1841502)
|
||||||
|
|
||||||
|
* Tue Jun 9 2020 Steve Dickson <steved@redhat.com> 2.3.3-34
|
||||||
|
- New nfsdclnts command added (bz 1841502)
|
||||||
|
|
||||||
|
* Mon May 18 2020 Steve Dickson <steved@redhat.com> 2.3.3-33
|
||||||
|
- manpage: Add a description of the 'nconnect' mount option (bz 1761352)
|
||||||
|
- nfsdclddb: Redname clddb-tool to nfsdclddb (bz 1836924)
|
||||||
|
|
||||||
|
* Wed May 6 2020 Steve Dickson <steved@redhat.com> 2.3.3-32
|
||||||
|
- junction: Fixed debug statement (bz 1831829)
|
||||||
|
- Userspace support for the latest nfsdcld daemon (bz 1817756)
|
||||||
|
|
||||||
* Fri Mar 6 2020 Steve Dickson <steved@redhat.com> 2.3.3-31
|
* Fri Mar 6 2020 Steve Dickson <steved@redhat.com> 2.3.3-31
|
||||||
- gssd: Closed a memory leak in find_keytab_entry() (bz 1809277)
|
- gssd: Closed a memory leak in find_keytab_entry() (bz 1809277)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user