summaryrefslogtreecommitdiffstats
path: root/sys/compat
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2003-03-13 22:45:43 +0000
committerjhb <jhb@FreeBSD.org>2003-03-13 22:45:43 +0000
commit34c953a7727e28704114630ad33222b9800cb199 (patch)
tree3d9830747caf0da273c7bb49c9d4666c52ee45ce /sys/compat
parent129be1daea4bcf956a4f29af69b443113059a502 (diff)
downloadFreeBSD-src-34c953a7727e28704114630ad33222b9800cb199.zip
FreeBSD-src-34c953a7727e28704114630ad33222b9800cb199.tar.gz
- Change the linux_[gs]et_os{name, release, s_version}() functions to
take a thread instead of a proc for their first argument. - Add a mutex to protect the system-wide Linux osname, osrelease, and oss_version variables. - Change linux_get_prison() to take a thread instead of a proc for its first argument and to use td_ucred rather than p_ucred. This is ok because a thread's prison does not change even though it's ucred might. - Also, change linux_get_prison() to return a struct prison * instead of a struct linux_prison * since it returns with the struct prison locked and this makes it easier to safely unlock the prison when we are done messing with it.
Diffstat (limited to 'sys/compat')
-rw-r--r--sys/compat/linprocfs/linprocfs.c4
-rw-r--r--sys/compat/linux/linux_ioctl.c2
-rw-r--r--sys/compat/linux/linux_mib.c202
-rw-r--r--sys/compat/linux/linux_mib.h12
-rw-r--r--sys/compat/linux/linux_misc.c4
5 files changed, 109 insertions, 115 deletions
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c
index e18e0c7..1f3e85f 100644
--- a/sys/compat/linprocfs/linprocfs.c
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -449,8 +449,8 @@ linprocfs_doversion(PFS_FILL_ARGS)
char osname[LINUX_MAX_UTSNAME];
char osrelease[LINUX_MAX_UTSNAME];
- linux_get_osname(td->td_proc, osname);
- linux_get_osrelease(td->td_proc, osrelease);
+ linux_get_osname(td, osname);
+ linux_get_osrelease(td, osrelease);
sbuf_printf(sb,
"%s version %s (des@freebsd.org) (gcc version " __VERSION__ ")"
diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c
index 2121845..b71cf6f 100644
--- a/sys/compat/linux/linux_ioctl.c
+++ b/sys/compat/linux/linux_ioctl.c
@@ -1596,7 +1596,7 @@ linux_ioctl_sound(struct thread *td, struct linux_ioctl_args *args)
return (ioctl(td, (struct ioctl_args *)args));
case LINUX_OSS_GETVERSION: {
- int version = linux_get_oss_version(td->td_proc);
+ int version = linux_get_oss_version(td);
return (copyout(&version, (void *)args->arg, sizeof(int)));
}
diff --git a/sys/compat/linux/linux_mib.c b/sys/compat/linux/linux_mib.c
index d9cdd07..53fee72 100644
--- a/sys/compat/linux/linux_mib.c
+++ b/sys/compat/linux/linux_mib.c
@@ -50,6 +50,9 @@ struct linux_prison {
SYSCTL_NODE(_compat, OID_AUTO, linux, CTLFLAG_RW, 0,
"Linux mode");
+static struct mtx osname_lock;
+MTX_SYSINIT(linux_osname, &osname_lock, "linux osname", MTX_DEF);
+
static char linux_osname[LINUX_MAX_UTSNAME] = "Linux";
static int
@@ -58,11 +61,11 @@ linux_sysctl_osname(SYSCTL_HANDLER_ARGS)
char osname[LINUX_MAX_UTSNAME];
int error;
- linux_get_osname(req->td->td_proc, osname);
+ linux_get_osname(req->td, osname);
error = sysctl_handle_string(oidp, osname, LINUX_MAX_UTSNAME, req);
if (error || req->newptr == NULL)
return (error);
- error = linux_set_osname(req->td->td_proc, osname);
+ error = linux_set_osname(req->td, osname);
return (error);
}
@@ -79,11 +82,11 @@ linux_sysctl_osrelease(SYSCTL_HANDLER_ARGS)
char osrelease[LINUX_MAX_UTSNAME];
int error;
- linux_get_osrelease(req->td->td_proc, osrelease);
+ linux_get_osrelease(req->td, osrelease);
error = sysctl_handle_string(oidp, osrelease, LINUX_MAX_UTSNAME, req);
if (error || req->newptr == NULL)
return (error);
- error = linux_set_osrelease(req->td->td_proc, osrelease);
+ error = linux_set_osrelease(req->td, osrelease);
return (error);
}
@@ -100,11 +103,11 @@ linux_sysctl_oss_version(SYSCTL_HANDLER_ARGS)
int oss_version;
int error;
- oss_version = linux_get_oss_version(req->td->td_proc);
+ oss_version = linux_get_oss_version(req->td);
error = sysctl_handle_int(oidp, &oss_version, 0, req);
if (error || req->newptr == NULL)
return (error);
- error = linux_set_oss_version(req->td->td_proc, oss_version);
+ error = linux_set_oss_version(req->td, oss_version);
return (error);
}
@@ -116,177 +119,168 @@ SYSCTL_PROC(_compat_linux, OID_AUTO, oss_version,
/*
* Returns holding the prison mutex if return non-NULL.
*/
-static struct linux_prison *
-linux_get_prison(struct proc *p)
+static struct prison *
+linux_get_prison(struct thread *td)
{
register struct prison *pr;
register struct linux_prison *lpr;
- if (!jailed(p->p_ucred))
+ KASSERT(td == curthread, ("linux_get_prison() called on !curthread"));
+ if (!jailed(td->td_ucred))
return (NULL);
-
- pr = p->p_ucred->cr_prison;
-
- /*
- * Rather than hold the prison mutex during allocation, check to
- * see if we need to allocate while holding the mutex, release it,
- * allocate, then once we've allocated the memory, check again to
- * see if it's still needed, and set if appropriate. If it's not,
- * we release the mutex again to FREE(), and grab it again so as
- * to release holding the lock.
- */
+ pr = td->td_ucred->cr_prison;
mtx_lock(&pr->pr_mtx);
if (pr->pr_linux == NULL) {
+ /*
+ * If we don't have a linux prison structure yet, allocate
+ * one. We have to handle the race where another thread
+ * could be adding a linux prison to this process already.
+ */
mtx_unlock(&pr->pr_mtx);
- MALLOC(lpr, struct linux_prison *, sizeof *lpr,
- M_PRISON, M_WAITOK|M_ZERO);
+ lpr = malloc(sizeof(struct linux_prison), M_PRISON,
+ M_WAITOK | M_ZERO);
mtx_lock(&pr->pr_mtx);
- if (pr->pr_linux == NULL) {
+ if (pr->pr_linux == NULL)
pr->pr_linux = lpr;
- } else {
- mtx_unlock(&pr->pr_mtx);
- FREE(lpr, M_PRISON);
- mtx_lock(&pr->pr_mtx);
- }
+ else
+ free(lpr, M_PRISON);
}
-
- return (pr->pr_linux);
+ return (pr);
}
void
-linux_get_osname(p, dst)
- struct proc *p;
- char *dst;
+linux_get_osname(struct thread *td, char *dst)
{
register struct prison *pr;
register struct linux_prison *lpr;
- if (p->p_ucred->cr_prison == NULL) {
- bcopy(linux_osname, dst, LINUX_MAX_UTSNAME);
- return;
- }
-
- pr = p->p_ucred->cr_prison;
-
- mtx_lock(&pr->pr_mtx);
- if (pr->pr_linux != NULL) {
- lpr = (struct linux_prison *)pr->pr_linux;
- if (lpr->pr_osname[0]) {
- bcopy(lpr->pr_osname, dst, LINUX_MAX_UTSNAME);
- mtx_unlock(&pr->pr_mtx);
- return;
+ pr = td->td_ucred->cr_prison;
+ if (pr != NULL) {
+ mtx_lock(&pr->pr_mtx);
+ if (pr->pr_linux != NULL) {
+ lpr = (struct linux_prison *)pr->pr_linux;
+ if (lpr->pr_osname[0]) {
+ bcopy(lpr->pr_osname, dst, LINUX_MAX_UTSNAME);
+ mtx_unlock(&pr->pr_mtx);
+ return;
+ }
}
+ mtx_unlock(&pr->pr_mtx);
}
- mtx_unlock(&pr->pr_mtx);
+
+ mtx_lock(&osname_lock);
bcopy(linux_osname, dst, LINUX_MAX_UTSNAME);
+ mtx_unlock(&osname_lock);
}
int
-linux_set_osname(p, osname)
- struct proc *p;
- char *osname;
+linux_set_osname(struct thread *td, char *osname)
{
- register struct linux_prison *lpr;
+ struct prison *pr;
+ struct linux_prison *lpr;
- lpr = linux_get_prison(p);
- if (lpr != NULL) {
+ pr = linux_get_prison(td);
+ if (pr != NULL) {
+ lpr = (struct linux_prison *)pr->pr_linux;
strcpy(lpr->pr_osname, osname);
- mtx_unlock(&p->p_ucred->cr_prison->pr_mtx);
+ mtx_unlock(&pr->pr_mtx);
} else {
+ mtx_lock(&osname_lock);
strcpy(linux_osname, osname);
+ mtx_unlock(&osname_lock);
}
return (0);
}
void
-linux_get_osrelease(p, dst)
- struct proc *p;
- char *dst;
+linux_get_osrelease(struct thread *td, char *dst)
{
register struct prison *pr;
struct linux_prison *lpr;
- if (p->p_ucred->cr_prison == NULL) {
- bcopy(linux_osrelease, dst, LINUX_MAX_UTSNAME);
- return;
- }
-
- pr = p->p_ucred->cr_prison;
-
- mtx_lock(&pr->pr_mtx);
- if (pr->pr_linux != NULL) {
- lpr = (struct linux_prison *) pr->pr_linux;
- if (lpr->pr_osrelease[0]) {
- bcopy(lpr->pr_osrelease, dst, LINUX_MAX_UTSNAME);
- mtx_unlock(&pr->pr_mtx);
- return;
+ pr = td->td_ucred->cr_prison;
+ if (pr != NULL) {
+ mtx_lock(&pr->pr_mtx);
+ if (pr->pr_linux != NULL) {
+ lpr = (struct linux_prison *)pr->pr_linux;
+ if (lpr->pr_osrelease[0]) {
+ bcopy(lpr->pr_osrelease, dst,
+ LINUX_MAX_UTSNAME);
+ mtx_unlock(&pr->pr_mtx);
+ return;
+ }
}
+ mtx_unlock(&pr->pr_mtx);
}
- mtx_unlock(&pr->pr_mtx);
+
+ mtx_lock(&osname_lock);
bcopy(linux_osrelease, dst, LINUX_MAX_UTSNAME);
+ mtx_unlock(&osname_lock);
}
int
-linux_set_osrelease(p, osrelease)
- struct proc *p;
- char *osrelease;
+linux_set_osrelease(struct thread *td, char *osrelease)
{
- register struct linux_prison *lpr;
+ struct prison *pr;
+ struct linux_prison *lpr;
- lpr = linux_get_prison(p);
- if (lpr != NULL) {
+ pr = linux_get_prison(td);
+ if (pr != NULL) {
+ lpr = (struct linux_prison *)pr->pr_linux;
strcpy(lpr->pr_osrelease, osrelease);
- mtx_unlock(&p->p_ucred->cr_prison->pr_mtx);
+ mtx_unlock(&pr->pr_mtx);
} else {
+ mtx_lock(&osname_lock);
strcpy(linux_osrelease, osrelease);
+ mtx_unlock(&osname_lock);
}
return (0);
}
int
-linux_get_oss_version(p)
- struct proc *p;
+linux_get_oss_version(struct thread *td)
{
register struct prison *pr;
register struct linux_prison *lpr;
int version;
- if (p->p_ucred->cr_prison == NULL)
- return (linux_oss_version);
-
- pr = p->p_ucred->cr_prison;
-
- mtx_lock(&pr->pr_mtx);
- if (pr->pr_linux != NULL) {
- lpr = (struct linux_prison *) pr->pr_linux;
- if (lpr->pr_oss_version) {
- version = lpr->pr_oss_version;
- } else {
- version = linux_oss_version;
+ pr = td->td_ucred->cr_prison;
+ if (pr != NULL) {
+ mtx_lock(&pr->pr_mtx);
+ if (pr->pr_linux != NULL) {
+ lpr = (struct linux_prison *)pr->pr_linux;
+ if (lpr->pr_oss_version) {
+ version = lpr->pr_oss_version;
+ mtx_unlock(&pr->pr_mtx);
+ return (version);
+ }
}
- } else {
- version = linux_oss_version;
+ mtx_unlock(&pr->pr_mtx);
}
- mtx_unlock(&pr->pr_mtx);
+ mtx_lock(&osname_lock);
+ version = linux_oss_version;
+ mtx_unlock(&osname_lock);
return (version);
}
int
-linux_set_oss_version(p, oss_version)
- struct proc *p;
- int oss_version;
+linux_set_oss_version(struct thread *td, int oss_version)
{
- register struct linux_prison *lpr;
+ struct prison *pr;
+ struct linux_prison *lpr;
- lpr = linux_get_prison(p);
- if (lpr != NULL) {
+ pr = linux_get_prison(td);
+ if (pr != NULL) {
+ lpr = (struct linux_prison *)pr->pr_linux;
lpr->pr_oss_version = oss_version;
- mtx_unlock(&p->p_ucred->cr_prison->pr_mtx);
+ mtx_unlock(&pr->pr_mtx);
} else {
+ mtx_lock(&osname_lock);
linux_oss_version = oss_version;
+ mtx_unlock(&osname_lock);
}
return (0);
diff --git a/sys/compat/linux/linux_mib.h b/sys/compat/linux/linux_mib.h
index 9e122ec..42d9d89 100644
--- a/sys/compat/linux/linux_mib.h
+++ b/sys/compat/linux/linux_mib.h
@@ -31,13 +31,13 @@
#ifndef _LINUX_MIB_H_
#define _LINUX_MIB_H_
-void linux_get_osname(struct proc *p, char *dst);
-int linux_set_osname(struct proc *p, char *osname);
+void linux_get_osname(struct thread *td, char *dst);
+int linux_set_osname(struct thread *td, char *osname);
-void linux_get_osrelease(struct proc *p, char *dst);
-int linux_set_osrelease(struct proc *p, char *osrelease);
+void linux_get_osrelease(struct thread *td, char *dst);
+int linux_set_osrelease(struct thread *td, char *osrelease);
-int linux_get_oss_version(struct proc *p);
-int linux_set_oss_version(struct proc *p, int oss_version);
+int linux_get_oss_version(struct thread *td);
+int linux_set_oss_version(struct thread *td, int oss_version);
#endif /* _LINUX_MIB_H_ */
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index c16ae88..8e86706 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -697,8 +697,8 @@ linux_newuname(struct thread *td, struct linux_newuname_args *args)
printf(ARGS(newuname, "*"));
#endif
- linux_get_osname(td->td_proc, osname);
- linux_get_osrelease(td->td_proc, osrelease);
+ linux_get_osname(td, osname);
+ linux_get_osrelease(td, osrelease);
bzero(&utsname, sizeof(utsname));
strlcpy(utsname.sysname, osname, LINUX_MAX_UTSNAME);
OpenPOWER on IntegriCloud