summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornr123932 <none@none>2007-03-30 01:55:41 -0700
committernr123932 <none@none>2007-03-30 01:55:41 -0700
commit8548bf79039833dba8615afdf63258b2cb122121 (patch)
treec9d7f506296f12858a99b42d94bda969bb1a4ebc
parent3a62633b4e364efc25704bee4e40b1107709521e (diff)
downloadillumos-gate-8548bf79039833dba8615afdf63258b2cb122121.tar.gz
6368753 Need a patch solution to 4522909 automountd hangs with executeable maps
6509943 Apparent deadlock between fork()'s use of lwp_suspend and NFS locking (Backout 4522909)
-rw-r--r--usr/src/cmd/fs.d/autofs/Makefile6
-rw-r--r--usr/src/cmd/fs.d/autofs/autod_main.c77
-rw-r--r--usr/src/cmd/fs.d/autofs/autod_mount.c129
-rw-r--r--usr/src/cmd/fs.d/autofs/automount.h26
-rw-r--r--usr/src/cmd/fs.d/autofs/ns_files.c75
-rw-r--r--usr/src/uts/common/os/condvar.c22
-rw-r--r--usr/src/uts/common/os/sig.c22
-rw-r--r--usr/src/uts/common/sys/klwp.h30
-rw-r--r--usr/src/uts/common/vm/vm_as.c27
-rw-r--r--usr/src/uts/intel/fs/proc/prmachdep.c12
-rw-r--r--usr/src/uts/sparc/fs/proc/prmachdep.c19
11 files changed, 310 insertions, 135 deletions
diff --git a/usr/src/cmd/fs.d/autofs/Makefile b/usr/src/cmd/fs.d/autofs/Makefile
index 47fb37668e..7365a9132a 100644
--- a/usr/src/cmd/fs.d/autofs/Makefile
+++ b/usr/src/cmd/fs.d/autofs/Makefile
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -85,9 +85,9 @@ POFILE= autofs.po
GREP= egrep
SED= sed
-$(AUTO) := LDLIBS += -lnsl -lsldap
+$(AUTO) := LDLIBS += -lnsl -lsldap -ldoor
$(MOUNT):= LDLIBS += -lnsl
-$(TYPEPROG) := LDLIBS += -lrpcsvc -lsocket -lnsl -lsldap -lkstat
+$(TYPEPROG) := LDLIBS += -lrpcsvc -lsocket -lnsl -lsldap -lkstat -ldoor
$(TYPEPROG) := LDFLAGS += -R/usr/lib/fs/$(FSTYPE)
CFLAGS += $(CCVERBOSE) -D_FILE_OFFSET_BITS=64
diff --git a/usr/src/cmd/fs.d/autofs/autod_main.c b/usr/src/cmd/fs.d/autofs/autod_main.c
index 1c0a51d7a1..cee127cb9b 100644
--- a/usr/src/cmd/fs.d/autofs/autod_main.c
+++ b/usr/src/cmd/fs.d/autofs/autod_main.c
@@ -60,6 +60,7 @@
#include <sys/thread.h>
#include <nfs/rnode.h>
#include <nfs/nfs.h>
+#include <wait.h>
static void autofs_doorfunc(void *, char *, size_t, door_desc_t *, uint_t);
static void autofs_setdoor(int);
@@ -77,6 +78,7 @@ static void usage();
static void warn_hup(int);
static void free_action_list();
static int start_autofs_svcs();
+static void automountd_wait_for_cleanup(pid_t);
/*
@@ -188,6 +190,50 @@ main(argc, argv)
openlog("automountd", LOG_PID, LOG_DAEMON);
(void) setlocale(LC_ALL, "");
+ /*
+ * Create the door_servers to manage fork/exec requests for
+ * mounts and executable automount maps
+ */
+ if ((did_fork_exec = door_create(automountd_do_fork_exec,
+ NULL, NULL)) == -1) {
+ syslog(LOG_ERR, "door_create failed: %m, Exiting.");
+ exit(errno);
+ }
+ if ((did_exec_map = door_create(automountd_do_exec_map,
+ NULL, NULL)) == -1) {
+ syslog(LOG_ERR, "door_create failed: %m, Exiting.");
+ if (door_revoke(did_fork_exec) == -1) {
+ syslog(LOG_ERR, "failed to door_revoke(%d) %m",
+ did_fork_exec);
+ }
+ exit(errno);
+ }
+ /*
+ * Before we become multithreaded we fork allowing the parent
+ * to become a door server to handle all mount and unmount
+ * requests. This works around a potential hang in using
+ * fork1() within a multithreaded environment
+ */
+
+ pid = fork1();
+ if (pid < 0) {
+ syslog(LOG_ERR,
+ "can't fork the automountd mount process %m");
+ if (door_revoke(did_fork_exec) == -1) {
+ syslog(LOG_ERR, "failed to door_revoke(%d) %m",
+ did_fork_exec);
+ }
+ if (door_revoke(did_exec_map) == -1) {
+ syslog(LOG_ERR, "failed to door_revoke(%d) %m",
+ did_exec_map);
+ }
+ exit(1);
+ } else if (pid > 0) {
+ /* this is the door server process */
+ automountd_wait_for_cleanup(pid);
+ }
+
+
(void) rwlock_init(&cache_lock, USYNC_THREAD, NULL);
(void) rwlock_init(&autofs_rddir_cache_lock, USYNC_THREAD, NULL);
@@ -220,8 +266,7 @@ main(argc, argv)
case 0:
break;
case -1:
- syslog(LOG_ERR, "error locking for %s: %s", AUTOMOUNTD,
- strerror(errno));
+ syslog(LOG_ERR, "error locking for %s: %m", AUTOMOUNTD);
exit(2);
default:
/* daemon was already running */
@@ -990,3 +1035,31 @@ encode_res(
(*results)->res_status = 0;
return (TRUE);
}
+
+static void
+automountd_wait_for_cleanup(pid_t pid)
+{
+ int status;
+ int child_exitval;
+
+ /*
+ * Wait for the main automountd process to exit so we cleanup
+ */
+ (void) waitpid(pid, &status, 0);
+
+ child_exitval = WEXITSTATUS(status);
+
+ /*
+ * Shutdown the door server for mounting and unmounting
+ * filesystems
+ */
+ if (door_revoke(did_fork_exec) == -1) {
+ syslog(LOG_ERR, "failed to door_revoke(%d) %m",
+ did_fork_exec);
+ }
+ if (door_revoke(did_exec_map) == -1) {
+ syslog(LOG_ERR, "failed to door_revoke(%d) %m",
+ did_exec_map);
+ }
+ exit(child_exitval);
+}
diff --git a/usr/src/cmd/fs.d/autofs/autod_mount.c b/usr/src/cmd/fs.d/autofs/autod_mount.c
index b5826a0a20..31055371ef 100644
--- a/usr/src/cmd/fs.d/autofs/autod_mount.c
+++ b/usr/src/cmd/fs.d/autofs/autod_mount.c
@@ -52,12 +52,13 @@
#include <limits.h>
#include <assert.h>
#include <fcntl.h>
+#include <strings.h>
#include "automount.h"
#include "replica.h"
static int unmount_mntpnt(struct mnttab *);
-static int fork_exec(char *, char *, char **, int);
+static int call_fork_exec(char *, char *, char **, int);
static void remove_browse_options(char *);
static int inherit_options(char *, char **);
@@ -373,7 +374,7 @@ mount_generic(special, fstype, opts, mntpnt, overlay)
newargv[i++] = special;
newargv[i++] = mntpnt;
newargv[i] = NULL;
- res = fork_exec(fstype, "mount", newargv, verbose);
+ res = call_fork_exec(fstype, "mount", newargv, verbose);
if (res == 0 && trace > 1) {
if (stat(mntpnt, &stbuf) == 0) {
trace_prt(1, " mount of %s dev=%x rdev=%x OK\n",
@@ -385,57 +386,58 @@ mount_generic(special, fstype, opts, mntpnt, overlay)
return (res);
}
-static int
-fork_exec(fstype, cmd, newargv, console)
- char *fstype;
- char *cmd;
- char **newargv;
- int console;
+void
+automountd_do_fork_exec(void *cookie, char *argp, size_t arg_size,
+ door_desc_t *dfd, uint_t n_desc)
{
- char path[MAXPATHLEN];
- int i;
int stat_loc;
int fd = 0;
struct stat stbuf;
int res;
int child_pid;
+ command_t *command;
+ char *newargv[ARGV_MAX];
+ int i;
- /* build the full path name of the fstype dependent command */
- (void) sprintf(path, "%s/%s/%s", VFS_PATH, fstype, cmd);
- if (stat(path, &stbuf) != 0) {
- res = errno;
- return (res);
+ command = (command_t *)argp;
+ if (sizeof (*command) != arg_size) {
+ res = EINVAL;
+ door_return((char *)&res, sizeof (res), NULL, 0);
}
- if (trace > 1) {
- trace_prt(1, " fork_exec: %s ", path);
- for (i = 2; newargv[i]; i++)
- trace_prt(0, "%s ", newargv[i]);
- trace_prt(0, "\n");
- }
-
-
- newargv[1] = cmd;
switch ((child_pid = fork1())) {
case -1:
syslog(LOG_ERR, "Cannot fork: %m");
- return (errno);
+ res = errno;
+ break;
case 0:
/*
* Child
*/
(void) setsid();
- fd = open(console ? "/dev/console" : "/dev/null", O_WRONLY);
+ fd = open(command->console ? "/dev/console" : "/dev/null",
+ O_WRONLY);
if (fd != -1) {
(void) dup2(fd, 1);
(void) dup2(fd, 2);
(void) close(fd);
}
- (void) execv(path, &newargv[1]);
+ for (i = 0; *command->argv[i]; i++) {
+ newargv[i] = strdup(command->argv[i]);
+ if (newargv[i] == (char *)NULL) {
+ syslog(LOG_ERR, "failed to copy argument '%s'"
+ " of %s: %m", command->argv[i],
+ command->file);
+ _exit(errno);
+ }
+ }
+ newargv[i] = NULL;
+
+ (void) execv(command->file, newargv);
if (errno == EACCES)
- syslog(LOG_ERR, "exec %s: %m", path);
+ syslog(LOG_ERR, "exec %s: %m", command->file);
_exit(errno);
default:
@@ -451,22 +453,25 @@ fork_exec(fstype, cmd, newargv, console)
WEXITSTATUS(stat_loc));
}
- return (WEXITSTATUS(stat_loc));
- } else
- if (WIFSIGNALED(stat_loc)) {
- if (trace > 1) {
+ res = WEXITSTATUS(stat_loc);
+ } else if (WIFSIGNALED(stat_loc)) {
+ if (trace > 1)
trace_prt(1,
" fork_exec: returns signal status %d\n",
WTERMSIG(stat_loc));
- }
+ res = 1;
} else {
if (trace > 1)
trace_prt(1,
" fork_exec: returns unknown status\n");
+ res = 1;
}
- return (1);
}
+ door_return((char *)&res, sizeof (res), NULL, 0);
+ trace_prt(1, "automountd_do_fork_exec, door return failed %s, %s\n",
+ command->file, strerror(errno));
+ door_return(NULL, 0, NULL, 0);
}
int
@@ -551,7 +556,7 @@ unmount_mntpnt(mnt)
newargv[2] = mountp;
newargv[3] = NULL;
- res = fork_exec(fstype, "umount", newargv, verbose);
+ res = call_fork_exec(fstype, "umount", newargv, verbose);
if (res == ENOENT) {
/*
* filesystem specific unmount command not found
@@ -646,3 +651,57 @@ hasrestrictopt(char *opts)
return (hasmntopt(&mt, MNTOPT_RESTRICT) != NULL);
}
+
+static int
+call_fork_exec(fstype, cmd, newargv, console)
+ char *fstype;
+ char *cmd;
+ char **newargv;
+ int console;
+{
+ command_t command;
+ door_arg_t darg;
+ char path[MAXPATHLEN];
+ struct stat stbuf;
+ int ret;
+ int sz;
+ int status;
+ int i;
+
+ bzero(&command, sizeof (command));
+ /* build the full path name of the fstype dependent command */
+ (void) snprintf(path, MAXPATHLEN, "%s/%s/%s", VFS_PATH, fstype, cmd);
+
+ if (stat(path, &stbuf) != 0) {
+ ret = errno;
+ return (ret);
+ }
+
+ strlcpy(command.file, path, MAXPATHLEN);
+ strlcpy(command.argv[0], path, MAXOPTSLEN);
+ for (i = 2; newargv[i]; i++) {
+ strlcpy(command.argv[i-1], newargv[i], MAXOPTSLEN);
+ }
+ if (trace > 1) {
+ trace_prt(1, " call_fork_exec: %s ", command.file);
+ for (i = 0; *command.argv[i]; i++)
+ trace_prt(0, "%s ", command.argv[i]);
+ trace_prt(0, "\n");
+ }
+
+ command.console = console;
+
+ darg.data_ptr = (char *)&command;
+ darg.data_size = sizeof (command);
+ darg.desc_ptr = NULL;
+ darg.desc_num = 0;
+ darg.rbuf = (char *)&status;
+ darg.rsize = sizeof (status);
+
+ ret = door_call(did_fork_exec, &darg);
+ if (trace > 1) {
+ trace_prt(1, " call_fork_exec: door_call failed %d\n", ret);
+ }
+
+ return (status);
+}
diff --git a/usr/src/cmd/fs.d/autofs/automount.h b/usr/src/cmd/fs.d/autofs/automount.h
index d9c098a4e0..5a4909b79f 100644
--- a/usr/src/cmd/fs.d/autofs/automount.h
+++ b/usr/src/cmd/fs.d/autofs/automount.h
@@ -36,6 +36,7 @@
#include <rpc/rpc.h>
#include <sys/fs/autofs.h>
#include <netinet/in.h> /* needed for sockaddr_in declaration */
+#include <door.h>
#ifdef MALLOC_DEBUG
#include <debug_alloc.h>
@@ -93,6 +94,8 @@ extern "C" {
#define INITDELAY 5
#define DELAY_BACKOFF 2
#define MAXDELAY 120
+#define ARGV_MAX 16
+#define VFS_PATH "/usr/lib/fs"
#define DELAY(delay) { \
(void) sleep(delay); \
delay *= DELAY_BACKOFF; \
@@ -224,6 +227,23 @@ struct myaddrs {
struct myaddrs *myaddrs_next;
};
+/*
+ * structure used to pass commands to the door servers
+ */
+
+typedef struct command {
+ char file[MAXPATHLEN];
+ char argv[ARGV_MAX][MAXOPTSLEN];
+ char key[MAXOPTSLEN];
+ int console;
+} command_t;
+
+/*
+ * globally visible door_server file descriptor
+ */
+int did_exec_map;
+int did_fork_exec;
+
extern time_t timenow; /* set at start of processing of each RPC call */
extern char self[];
extern int verbose;
@@ -375,6 +395,12 @@ extern int getnetmaskbynet(const struct in_addr, struct in_addr *);
extern int __nis_reset_state();
extern int __rpc_negotiate_uid(int);
+/*
+ * door_server functions to handle fork activity within the automounter
+ */
+void automountd_do_fork_exec(void *, char *, size_t, door_desc_t *, uint_t);
+void automountd_do_exec_map(void *, char *, size_t, door_desc_t *, uint_t);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/cmd/fs.d/autofs/ns_files.c b/usr/src/cmd/fs.d/autofs/ns_files.c
index f04318a350..21a9766007 100644
--- a/usr/src/cmd/fs.d/autofs/ns_files.c
+++ b/usr/src/cmd/fs.d/autofs/ns_files.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -22,7 +21,7 @@
/*
* ns_files.c
*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -46,10 +45,13 @@
#include <synch.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <strings.h>
#include "automount.h"
static int read_execout(char *key, char **lp, char *fname, char *line,
int linesz);
+static int call_read_execout(char *key, char **lp, char *fname, char *line,
+ int linesz);
static FILE *file_open(char *, char *, char **, char ***);
/*
@@ -114,14 +116,14 @@ getmapent_files(key, mapname, ml, stack, stkptr, iswildcard, isrestricted)
fname, key);
}
- rc = read_execout(key, &lp, fname, ml->linebuf, LINESZ);
+ rc = call_read_execout(key, &lp, fname, ml->linebuf, LINESZ);
if (rc != 0) {
nserr = __NSW_UNAVAIL;
goto done;
}
- if (lp == NULL || strlen(ml->linebuf) == 0) {
+ if (strlen(ml->linebuf) == 0) {
nserr = __NSW_NOTFOUND;
goto done;
}
@@ -643,3 +645,64 @@ read_execout(char *key, char **lp, char *fname, char *line, int linesz)
return (status);
}
}
+
+void
+automountd_do_exec_map(void *cookie, char *argp, size_t arg_size,
+ door_desc_t *dfd, uint_t n_desc)
+{
+ command_t *command;
+ char line[LINESZ];
+ char *lp;
+ int rc;
+
+ command = (command_t *)argp;
+
+ if (sizeof (*command) != arg_size) {
+ rc = 0;
+ syslog(LOG_ERR, "read_execout: invalid door arguments");
+ door_return((char *)&rc, sizeof (rc), NULL, 0);
+ }
+
+ rc = read_execout(command->key, &lp, command->file, line, LINESZ);
+
+ if (rc != 0) {
+ /*
+ * read_execout returned an error, return 0 to the door_client
+ * to indicate failure
+ */
+ rc = 0;
+ door_return((char *)&rc, sizeof (rc), NULL, 0);
+ } else {
+ door_return((char *)line, LINESZ, NULL, 0);
+ }
+ trace_prt(1, "automountd_do_exec_map, door return failed %s, %s\n",
+ command->file, strerror(errno));
+ door_return(NULL, 0, NULL, 0);
+}
+
+int
+call_read_execout(char *key, char **lp, char *fname, char *line,
+ int linesz)
+{
+ command_t command;
+ door_arg_t darg;
+ int ret;
+
+ bzero(&command, sizeof (command));
+ (void) strlcpy(command.file, fname, MAXPATHLEN);
+ (void) strlcpy(command.key, key, MAXOPTSLEN);
+
+ if (trace >= 1)
+ trace_prt(1, "call_read_execout %s %s\n", fname, key);
+ darg.data_ptr = (char *)&command;
+ darg.data_size = sizeof (command);
+ darg.desc_ptr = NULL;
+ darg.desc_num = 0;
+ darg.rbuf = line;
+ darg.rsize = linesz;
+
+ ret = door_call(did_exec_map, &darg);
+
+ lp = &line;
+ return (ret);
+}
diff --git a/usr/src/uts/common/os/condvar.c b/usr/src/uts/common/os/condvar.c
index 71f20c6b67..4ac03cbddb 100644
--- a/usr/src/uts/common/os/condvar.c
+++ b/usr/src/uts/common/os/condvar.c
@@ -555,49 +555,45 @@ cv_wait_stop(kcondvar_t *cvp, kmutex_t *mp, int wakeup_time)
(void) untimeout(id);
/*
- * Check for reasons to stop, and stop if lwp_nostop is zero.
+ * Check for reasons to stop, if lwp_nostop is not true.
* See issig_forreal() for explanations of the various stops.
- * Like issig_forreal(), we allow a PR_SUSPENDED/SUSPEND_NORMAL
- * to occur even if lwp_nostop is set.
*/
mutex_enter(&p->p_lock);
- while (!(p->p_flag & SEXITLWPS)) {
+ while (lwp->lwp_nostop == 0 && !(p->p_flag & SEXITLWPS)) {
/*
* Hold the lwp here for watchpoint manipulation.
*/
- if ((t->t_proc_flag & TP_PAUSE) && !lwp->lwp_nostop) {
+ if (t->t_proc_flag & TP_PAUSE) {
stop(PR_SUSPENDED, SUSPEND_PAUSE);
continue;
}
/*
* System checkpoint.
*/
- if ((t->t_proc_flag & TP_CHKPT) && !lwp->lwp_nostop) {
+ if (t->t_proc_flag & TP_CHKPT) {
stop(PR_CHECKPOINT, 0);
continue;
}
/*
* Honor fork1(), watchpoint activity (remapping a page),
- * and lwp_suspend() regardless of whether lwp_nostop is
- * set but not if lwp_nostop_r is set (to avoid a recursive
- * call to prstop()).
+ * and lwp_suspend() requests.
*/
- if (((p->p_flag & (SHOLDFORK1|SHOLDWATCH)) ||
- (t->t_proc_flag & TP_HOLDLWP)) && !lwp->lwp_nostop_r) {
+ if ((p->p_flag & (SHOLDFORK1|SHOLDWATCH)) ||
+ (t->t_proc_flag & TP_HOLDLWP)) {
stop(PR_SUSPENDED, SUSPEND_NORMAL);
continue;
}
/*
* Honor /proc requested stop.
*/
- if ((t->t_proc_flag & TP_PRSTOP) && !lwp->lwp_nostop) {
+ if (t->t_proc_flag & TP_PRSTOP) {
stop(PR_REQUESTED, 0);
}
/*
* If some lwp in the process has already stopped
* showing PR_JOBCONTROL, stop in sympathy with it.
*/
- if (p->p_stopsig && !lwp->lwp_nostop && (t != p->p_agenttp)) {
+ if (p->p_stopsig && t != p->p_agenttp) {
stop(PR_JOBCONTROL, p->p_stopsig);
continue;
}
diff --git a/usr/src/uts/common/os/sig.c b/usr/src/uts/common/os/sig.c
index 5c72fb749b..69c1074816 100644
--- a/usr/src/uts/common/os/sig.c
+++ b/usr/src/uts/common/os/sig.c
@@ -447,10 +447,10 @@ issig_justlooking(void)
if ((lwp->lwp_asleep && MUSTRETURN(p, t)) ||
(p->p_flag & (SEXITLWPS|SKILLED)) ||
- (!lwp->lwp_nostop_r && ((p->p_flag & (SHOLDFORK1|SHOLDWATCH)) |
- (t->t_proc_flag & TP_HOLDLWP))) ||
- (!lwp->lwp_nostop && (p->p_stopsig | (t->t_proc_flag &
- (TP_PRSTOP|TP_CHKPT|TP_PAUSE)))) ||
+ (lwp->lwp_nostop == 0 &&
+ (p->p_stopsig | (p->p_flag & (SHOLDFORK1|SHOLDWATCH)) |
+ (t->t_proc_flag &
+ (TP_PRSTOP|TP_HOLDLWP|TP_CHKPT|TP_PAUSE)))) ||
lwp->lwp_cursig)
return (1);
@@ -588,15 +588,9 @@ issig_forreal(void)
* or is executing lwp_suspend() on this lwp.
* Again, go back to top of loop to check if an exit
* or hold event has occurred while stopped.
- * We explicitly allow this form of stopping of one
- * lwp in a process by another lwp in the same process,
- * even if lwp->lwp_nostop is set, because otherwise a
- * process can become deadlocked on a fork1().
- * Allow this only if lwp_nostop_r is not set,
- * to avoid a recursive call to prstop().
*/
if (((p->p_flag & (SHOLDFORK1|SHOLDWATCH)) ||
- (t->t_proc_flag & TP_HOLDLWP)) && !lwp->lwp_nostop_r) {
+ (t->t_proc_flag & TP_HOLDLWP)) && !lwp->lwp_nostop) {
stop(PR_SUSPENDED, SUSPEND_NORMAL);
continue;
}
@@ -863,11 +857,9 @@ stop(int why, int what)
/*
* Make sure we don't deadlock on a recursive call to prstop().
- * prstop() sets the lwp_nostop_r flag and increments lwp_nostop.
+ * prstop() sets the lwp_nostop flag.
*/
- if (lwp->lwp_nostop_r ||
- (lwp->lwp_nostop &&
- (why != PR_SUSPENDED || what != SUSPEND_NORMAL)))
+ if (lwp->lwp_nostop)
return;
/*
diff --git a/usr/src/uts/common/sys/klwp.h b/usr/src/uts/common/sys/klwp.h
index 7dea5b4941..93d1e9816f 100644
--- a/usr/src/uts/common/sys/klwp.h
+++ b/usr/src/uts/common/sys/klwp.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -160,34 +160,12 @@ typedef struct _klwp {
struct itimerval lwp_timer[3];
/*
- * There are a number of places where you do not wish an lwp to
- * be stopped due to some interaction with other lwps in the process.
- * In these cases the lwp_nostop value is incremented. At places where
- * the lwp would normally be stopped the stop is allowed if lwp_nostop
- * is zero. There are a very few cases where even if lwp_nostop is set
- * we need to allow the lwp to stop. In those cases the lwp is
- * stopped if lwp_nostop_r is not set regardless of the state of
- * lwp_nostop. These conditions are:
- *
- * 1. In issig_forreal() when another lwp is undergoing fork1()
- * or watchpoint activity (p_flag contains either SHOLDFORK1 or
- * SHOLDWATCH or t_proc_flag contains TP_HOLDLWP)
- *
- * 2. In stop() when the why argument is not PR_SUSPENDED or the what
- * argument is not SUSPEND_NORMAL.
- *
- * 3. In cv_wait_stop() when another lwp is undergoing fork1() or
- * watchpoint activity (p_flag contains either SHOLDFORK1 or
- * SHOLDWATCH or t_proc_flag contains TP_HOLDLWP)
- *
- * lwp_nostop_r is set in prstop(). ie we honour the presence of
- * SHOLDFORK1 or SHOLDWATCH or TP_HOLDLWP in the case of
- * stop(PR_SUSPENDED, SUSPEND_NORMAL)
+ * used to stop/alert lwps
*/
char lwp_unused;
char lwp_state; /* Running in User/Kernel mode (no lock req) */
- ushort_t lwp_nostop; /* Don't stop this lwp except SUSPEND_NORMAL */
- ushort_t lwp_nostop_r; /* Don't stop this lwp (avoid recursion) */
+ ushort_t lwp_nostop; /* Don't stop this lwp (no lock required) */
+ ushort_t lwp_pad; /* Reserved for future use */
/*
* Last failed privilege.
diff --git a/usr/src/uts/common/vm/vm_as.c b/usr/src/uts/common/vm/vm_as.c
index 801e55659c..42df064cc2 100644
--- a/usr/src/uts/common/vm/vm_as.c
+++ b/usr/src/uts/common/vm/vm_as.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -878,10 +878,8 @@ retry:
* for a pagefault. This is to avoid deadlock while debugging
* a process via /proc over NFS (in particular).
*/
- if (lwp != NULL) {
+ if (lwp != NULL)
lwp->lwp_nostop++;
- lwp->lwp_nostop_r++;
- }
/*
* same length must be used when we softlock and softunlock.
@@ -959,10 +957,8 @@ retry:
seg = as_segat(as, raddr);
if (seg == NULL) {
AS_LOCK_EXIT(as, &as->a_lock);
- if ((lwp != NULL) && (!is_xhat)) {
+ if ((lwp != NULL) && (!is_xhat))
lwp->lwp_nostop--;
- lwp->lwp_nostop_r--;
- }
return (FC_NOMAP);
}
@@ -1042,10 +1038,9 @@ retry:
}
if (as_lock_held)
AS_LOCK_EXIT(as, &as->a_lock);
- if ((lwp != NULL) && (!is_xhat)) {
+ if ((lwp != NULL) && (!is_xhat))
lwp->lwp_nostop--;
- lwp->lwp_nostop_r--;
- }
+
/*
* If the lower levels returned EDEADLK for a fault,
* It means that we should retry the fault. Let's wait
@@ -1083,10 +1078,8 @@ retry:
* for a pagefault. This is to avoid deadlock while debugging
* a process via /proc over NFS (in particular).
*/
- if (lwp != NULL) {
+ if (lwp != NULL)
lwp->lwp_nostop++;
- lwp->lwp_nostop_r++;
- }
raddr = (caddr_t)((uintptr_t)addr & (uintptr_t)PAGEMASK);
rsize = (((size_t)(addr + size) + PAGEOFFSET) & PAGEMASK) -
@@ -1096,10 +1089,8 @@ retry:
seg = as_segat(as, raddr);
if (seg == NULL) {
AS_LOCK_EXIT(as, &as->a_lock);
- if (lwp != NULL) {
+ if (lwp != NULL)
lwp->lwp_nostop--;
- lwp->lwp_nostop_r--;
- }
return (FC_NOMAP);
}
@@ -1116,10 +1107,8 @@ retry:
break;
}
AS_LOCK_EXIT(as, &as->a_lock);
- if (lwp != NULL) {
+ if (lwp != NULL)
lwp->lwp_nostop--;
- lwp->lwp_nostop_r--;
- }
/*
* If the lower levels returned EDEADLK for a fault,
* It means that we should retry the fault. Let's wait
diff --git a/usr/src/uts/intel/fs/proc/prmachdep.c b/usr/src/uts/intel/fs/proc/prmachdep.c
index f9a9fc3247..caebfab916 100644
--- a/usr/src/uts/intel/fs/proc/prmachdep.c
+++ b/usr/src/uts/intel/fs/proc/prmachdep.c
@@ -433,11 +433,11 @@ prstop(int why, int what)
struct regs *r = lwptoregs(lwp);
/*
- * Make sure we don't deadlock on a recursive call to prstop().
- * stop() tests the lwp_nostop_r and lwp_nostop flags.
+ * Make sure we don't deadlock on a recursive call
+ * to prstop(). stop() tests the lwp_nostop flag.
*/
- lwp->lwp_nostop_r++;
- lwp->lwp_nostop++;
+ ASSERT(lwp->lwp_nostop == 0);
+ lwp->lwp_nostop = 1;
if (copyin_nowatch((caddr_t)r->r_pc, &lwp->lwp_pcb.pcb_instr,
sizeof (lwp->lwp_pcb.pcb_instr)) == 0)
@@ -448,8 +448,8 @@ prstop(int why, int what)
}
(void) save_syscall_args();
- lwp->lwp_nostop--;
- lwp->lwp_nostop_r--;
+ ASSERT(lwp->lwp_nostop == 1);
+ lwp->lwp_nostop = 0;
}
/*
diff --git a/usr/src/uts/sparc/fs/proc/prmachdep.c b/usr/src/uts/sparc/fs/proc/prmachdep.c
index 3d27ecff08..bca9d0bb2d 100644
--- a/usr/src/uts/sparc/fs/proc/prmachdep.c
+++ b/usr/src/uts/sparc/fs/proc/prmachdep.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -881,11 +880,11 @@ prstop(int why, int what)
extern void fp_prsave(kfpu_t *);
/*
- * Make sure we don't deadlock on a recursive call to prstop().
- * stop() tests the lwp_nostop_r and lwp_nostop flags.
+ * Make sure we don't deadlock on a recursive call
+ * to prstop(). stop() tests the lwp_nostop flag.
*/
- lwp->lwp_nostop_r++;
- lwp->lwp_nostop++;
+ ASSERT(lwp->lwp_nostop == 0);
+ lwp->lwp_nostop = 1;
(void) flush_user_windows_to_stack(NULL);
if (lwp->lwp_pcb.pcb_step != STEP_NONE)
(void) prundostep();
@@ -968,8 +967,8 @@ prstop(int why, int what)
}
(void) save_syscall_args();
- lwp->lwp_nostop--;
- lwp->lwp_nostop_r--;
+ ASSERT(lwp->lwp_nostop == 1);
+ lwp->lwp_nostop = 0;
}
/*