Compare commits
8 Commits
imports/c8
...
c8
Author | SHA1 | Date | |
---|---|---|---|
|
c713474ed8 | ||
|
6d474dfbc4 | ||
|
944240a27c | ||
|
d551f79e6d | ||
|
39bd9e53dd | ||
|
0507dd6161 | ||
|
b7b45d88ad | ||
|
1292498303 |
@ -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
|
||||
--- nfs-utils-2.3.1/systemd/nfs-server.service.orig 2018-01-19 10:25:38.153513857 -0500
|
||||
+++ nfs-utils-2.3.1/systemd/nfs-server.service 2018-01-19 10:30:52.977245126 -0500
|
||||
@@ -26,6 +26,7 @@ Type=oneshot
|
||||
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.3/systemd/nfs-server.service.orig 2020-12-11 09:05:23.499222371 -0500
|
||||
+++ nfs-utils-2.3.3/systemd/nfs-server.service 2020-12-11 09:06:38.970186395 -0500
|
||||
@@ -23,6 +23,7 @@ Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStartPre=/usr/sbin/exportfs -r
|
||||
ExecStartPre=-/usr/sbin/exportfs -r
|
||||
ExecStart=/usr/sbin/rpc.nfsd
|
||||
+ExecStart=-/bin/sh -c 'if systemctl -q is-active gssproxy; then systemctl reload gssproxy ; fi'
|
||||
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);
|
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]
|
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;
|
||||
}
|
||||
|
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);
|
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>
|
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):
|
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
|
||||
URL: http://linux-nfs.org/
|
||||
Version: 2.3.3
|
||||
Release: 35%{?dist}
|
||||
Release: 59%{?dist}
|
||||
Epoch: 1
|
||||
|
||||
# group all 32bit related archs
|
||||
@ -61,6 +61,54 @@ 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
|
||||
|
||||
Patch100: nfs-utils-1.2.1-statdpath-man.patch
|
||||
Patch101: nfs-utils-1.2.1-exp-subtree-warn-off.patch
|
||||
Patch102: nfs-utils-2.3.3-idmap-errmsg.patch
|
||||
@ -128,16 +176,8 @@ developing programs which use the libnfsidmap library.
|
||||
|
||||
|
||||
%description
|
||||
The nfs-utils package provides a daemon for the kernel NFS server and
|
||||
related tools, which provides a much higher level of performance than the
|
||||
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.
|
||||
The nfs-utils package provides various utilities for use with NFS
|
||||
clients and servers.
|
||||
|
||||
%prep
|
||||
%autosetup -p1
|
||||
@ -223,8 +263,6 @@ done
|
||||
cat /etc/group | cut -d':' -f 1 | grep --quiet rpcuser 2>/dev/null
|
||||
if [ "$?" -eq 1 ]; then
|
||||
/usr/sbin/groupadd -g %{rpcuser_uid} rpcuser >/dev/null 2>&1 || :
|
||||
else
|
||||
/usr/sbin/groupmod -g %{rpcuser_uid} rpcuser >/dev/null 2>&1 || :
|
||||
fi
|
||||
|
||||
# Create rpcuser uid as long as it does not already exist.
|
||||
@ -253,11 +291,6 @@ if [ $? -eq 1 ]; then
|
||||
fi
|
||||
|
||||
%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
|
||||
# Initial installation
|
||||
/bin/systemctl enable nfs-client.target >/dev/null 2>&1 || :
|
||||
@ -270,8 +303,6 @@ if [ $1 -eq 0 ]; then
|
||||
%systemd_preun nfs-client.target
|
||||
%systemd_preun nfs-server.server
|
||||
|
||||
rm -rf /var/lib/nfs/statd
|
||||
rm -rf /var/lib/nfs/v4recovery
|
||||
fi
|
||||
|
||||
%postun
|
||||
@ -280,6 +311,11 @@ fi
|
||||
|
||||
/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
|
||||
/bin/systemctl try-restart gssproxy || :
|
||||
|
||||
@ -324,6 +360,9 @@ fi
|
||||
%{_sbindir}/nfsdclddb
|
||||
%{_sbindir}/nfsdcld
|
||||
%{_sbindir}/nfsdclnts
|
||||
%{_sbindir}/rpcctl
|
||||
%{_libexecdir}/nfsrahead
|
||||
%{_udevrulesdir}/99-nfs.rules
|
||||
%{_mandir}/*/*
|
||||
%{_pkgdir}/*/*
|
||||
|
||||
@ -347,6 +386,89 @@ fi
|
||||
%{_libdir}/libnfsidmap.so
|
||||
|
||||
%changelog
|
||||
* 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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user