summaryrefslogtreecommitdiff
path: root/usr/src/uts/common
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common')
-rw-r--r--usr/src/uts/common/brand/lx/autofs/lx_autofs.c3
-rw-r--r--usr/src/uts/common/brand/lx/procfs/lx_proc.h9
-rw-r--r--usr/src/uts/common/brand/lx/procfs/lx_prsubr.c259
-rw-r--r--usr/src/uts/common/brand/lx/procfs/lx_prvnops.c295
-rw-r--r--usr/src/uts/common/brand/lx/syscall/lx_mount.c167
-rw-r--r--usr/src/uts/common/brand/lx/syscall/lx_stat.c13
-rw-r--r--usr/src/uts/common/fs/lookup.c3
-rw-r--r--usr/src/uts/common/sys/file.h5
8 files changed, 528 insertions, 226 deletions
diff --git a/usr/src/uts/common/brand/lx/autofs/lx_autofs.c b/usr/src/uts/common/brand/lx/autofs/lx_autofs.c
index 730deae80e..364215d026 100644
--- a/usr/src/uts/common/brand/lx/autofs/lx_autofs.c
+++ b/usr/src/uts/common/brand/lx/autofs/lx_autofs.c
@@ -2208,6 +2208,9 @@ lx_autofs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp,
if (error != ENOENT)
return (error);
+ if (flags & __FLXNOAUTO)
+ return (ENOENT);
+
if (data->lav_catatonic)
return (ENOENT);
diff --git a/usr/src/uts/common/brand/lx/procfs/lx_proc.h b/usr/src/uts/common/brand/lx/procfs/lx_proc.h
index be95e7e471..f4d18fffc1 100644
--- a/usr/src/uts/common/brand/lx/procfs/lx_proc.h
+++ b/usr/src/uts/common/brand/lx/procfs/lx_proc.h
@@ -22,6 +22,7 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2019 Joyent, Inc.
+ * Copyright 2021 OmniOS Community Edition (OmniOSce) Association.
*/
#ifndef _LX_PROC_H
@@ -135,6 +136,8 @@ typedef enum lxpr_nodetype {
LXPR_PID_TASK_IDDIR, /* /proc/<pid>/task/<tid> */
LXPR_PID_FDDIR, /* /proc/<pid>/fd */
LXPR_PID_FD_FD, /* /proc/<pid>/fd/nn */
+ LXPR_PID_FDINFODIR, /* /proc/<pid>/fdinfo */
+ LXPR_PID_FDINFO_FD, /* /proc/<pid>/fdinfo/nn */
LXPR_PID_UIDMAP, /* /proc/<pid>/uid_map */
LXPR_PID_TID_AUXV, /* /proc/<pid>/task/<tid>/auxv */
LXPR_PID_TID_CGROUP, /* /proc/<pid>/task/<tid>/cgroup */
@@ -158,6 +161,8 @@ typedef enum lxpr_nodetype {
LXPR_PID_TID_STATUS, /* /proc/<pid>/task/<tid>/status */
LXPR_PID_TID_FDDIR, /* /proc/<pid>/task/<tid>/fd */
LXPR_PID_TID_FD_FD, /* /proc/<pid>/task/<tid>/fd/nn */
+ LXPR_PID_TID_FDINFODIR, /* /proc/<pid>/task/<tid>/fdinfo */
+ LXPR_PID_TID_FDINFO_FD, /* /proc/<pid>/task/<tid>/fdinfo/nn */
LXPR_PID_TID_UIDMAP, /* /proc/<pid>/task/<tid>/uid_map */
LXPR_CGROUPS, /* /proc/cgroups */
LXPR_CMDLINE, /* /proc/cmdline */
@@ -338,6 +343,8 @@ extern lxpr_node_t *lxpr_getnode(vnode_t *, lxpr_nodetype_t, proc_t *, int);
extern void lxpr_freenode(lxpr_node_t *);
extern vnode_t *lxpr_lookup_fdnode(vnode_t *, const char *);
extern int lxpr_readlink_fdnode(lxpr_node_t *, char *, size_t);
+extern vnode_t *lxpr_lookup_fdinfonode(vnode_t *, const char *);
+extern int lxpr_open_flags_convert(offset_t, uint32_t);
typedef struct lxpr_uiobuf {
uio_t *uiop;
@@ -370,6 +377,8 @@ extern proc_t *lxpr_lock_pid(lxpr_node_t *, pid_t, zombok_t, kthread_t **);
extern void lxpr_unlock(proc_t *);
extern netstack_t *lxpr_netstack(lxpr_node_t *);
extern void lxpr_fixpid(zone_t *, proc_t *, pid_t *, pid_t *);
+extern file_t *lxpr_getf(proc_t *, uint_t, short *);
+extern void lxpr_releasef(proc_t *, uint_t);
#ifdef __cplusplus
}
diff --git a/usr/src/uts/common/brand/lx/procfs/lx_prsubr.c b/usr/src/uts/common/brand/lx/procfs/lx_prsubr.c
index aa778d1cc8..967d594913 100644
--- a/usr/src/uts/common/brand/lx/procfs/lx_prsubr.c
+++ b/usr/src/uts/common/brand/lx/procfs/lx_prsubr.c
@@ -22,6 +22,7 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2019 Joyent, Inc.
+ * Copyright 2021 OmniOS Community Edition (OmniOSce) Association.
*/
/*
@@ -35,7 +36,9 @@
#include <sys/vmsystm.h>
#include <sys/prsystm.h>
#include <sys/brand.h>
+#include <sys/fcntl.h>
#include <sys/lx_brand.h>
+#include <sys/lx_fcntl.h>
#include "lx_proc.h"
@@ -352,6 +355,62 @@ lxpr_unlock(proc_t *p)
mutex_exit(&p->p_lock);
}
+file_t *
+lxpr_getf(proc_t *p, uint_t fd, short *flag)
+{
+ uf_entry_t *ufp;
+ uf_info_t *fip;
+ file_t *fp;
+
+ ASSERT(MUTEX_HELD(&p->p_lock) && (p->p_proc_flag & P_PR_LOCK));
+
+ fip = P_FINFO(p);
+
+ if (fd >= fip->fi_nfiles)
+ return (NULL);
+
+ /*
+ * Drop p_lock, but keep the process P_PR_LOCK'd to prevent it from
+ * going away while we dereference into fi_list.
+ */
+ mutex_exit(&p->p_lock);
+ mutex_enter(&fip->fi_lock);
+ UF_ENTER(ufp, fip, fd);
+ if ((fp = ufp->uf_file) != NULL && fp->f_count > 0) {
+ if (flag != NULL)
+ *flag = ufp->uf_flag;
+ ufp->uf_refcnt++;
+ } else {
+ fp = NULL;
+ }
+ UF_EXIT(ufp);
+ mutex_exit(&fip->fi_lock);
+ mutex_enter(&p->p_lock);
+
+ return (fp);
+}
+
+void
+lxpr_releasef(proc_t *p, uint_t fd)
+{
+ uf_entry_t *ufp;
+ uf_info_t *fip;
+
+ ASSERT(MUTEX_HELD(&p->p_lock) && (p->p_proc_flag & P_PR_LOCK));
+
+ fip = P_FINFO(p);
+
+ mutex_exit(&p->p_lock);
+ mutex_enter(&fip->fi_lock);
+ UF_ENTER(ufp, fip, fd);
+ ASSERT3U(ufp->uf_refcnt, >, 0);
+ ufp->uf_refcnt--;
+ UF_EXIT(ufp);
+ mutex_exit(&fip->fi_lock);
+ mutex_enter(&p->p_lock);
+}
+
+
void
lxpr_initnodecache()
{
@@ -366,7 +425,6 @@ lxpr_fininodecache()
kmem_cache_destroy(lxpr_node_cache);
}
-/* ARGSUSED */
static int
lxpr_node_constructor(void *buf, void *un, int kmflags)
{
@@ -383,7 +441,6 @@ lxpr_node_constructor(void *buf, void *un, int kmflags)
return (0);
}
-/* ARGSUSED */
static void
lxpr_node_destructor(void *buf, void *un)
{
@@ -586,8 +643,17 @@ lxpr_getnode(vnode_t *dp, lxpr_nodetype_t type, proc_t *p, int desc)
vp->v_type = VLNK;
break;
+ case LXPR_PID_FDINFO_FD:
+ case LXPR_PID_TID_FDINFO_FD:
+ ASSERT(p != NULL);
+ lxpnp->lxpr_mode = 0400; /* read by owner only */
+ vp->v_type = VREG;
+ break;
+
case LXPR_PID_FDDIR:
case LXPR_PID_TID_FDDIR:
+ case LXPR_PID_FDINFODIR:
+ case LXPR_PID_TID_FDINFODIR:
ASSERT(p != NULL);
vp->v_type = VDIR;
lxpnp->lxpr_mode = 0500; /* read-search by owner only */
@@ -661,6 +727,27 @@ lxpr_freenode(lxpr_node_t *lxpnp)
kmem_cache_free(lxpr_node_cache, lxpnp);
}
+static int
+lxpr_parse_fdnode_num(const char *name)
+{
+ char *endptr = NULL;
+ long num;
+ int fd;
+
+ if (ddi_strtol(name, &endptr, 10, &num) != 0) {
+ return (-1);
+ } else if (name[0] < '0' || name[0] > '9' || *endptr != '\0') {
+ /*
+ * ddi_strtol allows leading spaces and trailing garbage
+ * We do not tolerate such foolishness.
+ */
+ return (-1);
+ } else if ((fd = (int)num) < 0) {
+ return (-1);
+ }
+ return (fd);
+}
+
/*
* Attempt to locate vnode for /proc/<pid>/fd/<#>.
*/
@@ -669,34 +756,20 @@ lxpr_lookup_fdnode(vnode_t *dvp, const char *name)
{
lxpr_node_t *lxdp = VTOLXP(dvp);
lxpr_node_t *lxfp;
- char *endptr = NULL;
- long num;
int fd;
proc_t *p;
vnode_t *vp = NULL;
file_t *fp;
- uf_entry_t *ufp;
- uf_info_t *fip;
ASSERT(lxdp->lxpr_type == LXPR_PID_FDDIR ||
lxdp->lxpr_type == LXPR_PID_TID_FDDIR);
- if (ddi_strtol(name, &endptr, 10, &num) != 0) {
- return (NULL);
- } else if (name[0] < '0' || name[0] > '9' || *endptr != '\0') {
- /*
- * ddi_strtol allows leading spaces and trailing garbage
- * We do not tolerate such foolishness.
- */
+ if ((fd = lxpr_parse_fdnode_num(name)) == -1)
return (NULL);
- } else if ((fd = (int)num) < 0) {
- return (NULL);
- }
/* Lock the owner process */
- if ((p = lxpr_lock(lxdp, NO_ZOMB)) == NULL) {
+ if ((p = lxpr_lock(lxdp, NO_ZOMB)) == NULL)
return (NULL);
- }
/* Not applicable to processes which are system-owned. */
if (p->p_as == &kas) {
@@ -706,50 +779,38 @@ lxpr_lookup_fdnode(vnode_t *dvp, const char *name)
lxfp = lxpr_getnode(dvp, LXPR_PID_FD_FD, p, fd);
- /*
- * Drop p_lock, but keep the process P_PR_LOCK'd to prevent it from
- * going away while we dereference into fi_list.
- */
- fip = P_FINFO(p);
- mutex_exit(&p->p_lock);
- mutex_enter(&fip->fi_lock);
- if (fd < fip->fi_nfiles) {
- UF_ENTER(ufp, fip, fd);
- if ((fp = ufp->uf_file) != NULL) {
- vp = fp->f_vnode;
- VN_HOLD(vp);
- }
- UF_EXIT(ufp);
+ if ((fp = lxpr_getf(p, fd, NULL)) != NULL) {
+ vp = fp->f_vnode;
+ VN_HOLD(vp);
+ lxpr_releasef(p, fd);
}
- mutex_exit(&fip->fi_lock);
if (vp == NULL) {
- mutex_enter(&p->p_lock);
lxpr_unlock(p);
lxpr_freenode(lxfp);
return (NULL);
- } else {
- /*
- * Fill in the lxpr_node so future references will be able to
- * find the underlying vnode. The vnode is held on the realvp.
- */
- lxfp->lxpr_realvp = vp;
-
- /*
- * For certain entries (sockets, pipes, etc), Linux expects a
- * bogus-named symlink. If that's the case, report the type as
- * VNON to bypass link-following elsewhere in the vfs system.
- *
- * See lxpr_readlink for more details.
- */
- if (lxpr_readlink_fdnode(lxfp, NULL, 0) == 0)
- LXPTOV(lxfp)->v_type = VNON;
}
- mutex_enter(&p->p_lock);
+ /*
+ * Fill in the lxpr_node so future references will be able to
+ * find the underlying vnode. The vnode is held on the realvp.
+ */
+ lxfp->lxpr_realvp = vp;
+ vp = LXPTOV(lxfp);
+
+ /*
+ * For certain entries (sockets, pipes, etc), Linux expects a
+ * bogus-named symlink. If that's the case, report the type as
+ * VNON to bypass link-following elsewhere in the vfs system.
+ *
+ * See lxpr_readlink for more details.
+ */
+ if (lxpr_readlink_fdnode(lxfp, NULL, 0) == 0)
+ vp->v_type = VNON;
+
lxpr_unlock(p);
- ASSERT(LXPTOV(lxfp) != NULL);
- return (LXPTOV(lxfp));
+ ASSERT(vp != NULL);
+ return (vp);
}
/*
@@ -784,7 +845,95 @@ lxpr_readlink_fdnode(lxpr_node_t *lxpnp, char *bp, size_t len)
}
/*
- * Translate a Linux core_pattern path to a native Illumos one, by replacing
+ * Attempt to locate vnode for /proc/<pid>/fdinfo/<#>.
+ */
+vnode_t *
+lxpr_lookup_fdinfonode(vnode_t *dvp, const char *name)
+{
+ lxpr_node_t *lxdp = VTOLXP(dvp);
+ lxpr_node_t *lxfp;
+ proc_t *p;
+ int fd;
+
+ ASSERT(lxdp->lxpr_type == LXPR_PID_FDINFODIR);
+
+ if ((fd = lxpr_parse_fdnode_num(name)) == -1)
+ return (NULL);
+
+ /* Lock the owner process */
+ if ((p = lxpr_lock(lxdp, NO_ZOMB)) == NULL)
+ return (NULL);
+
+ /* Not applicable to processes which are system-owned. */
+ if (p->p_as == &kas) {
+ lxpr_unlock(p);
+ return (NULL);
+ }
+
+ lxfp = lxpr_getnode(dvp, LXPR_PID_FDINFO_FD, p, fd);
+
+ lxpr_unlock(p);
+ ASSERT(LXPTOV(lxfp) != NULL);
+ return (LXPTOV(lxfp));
+}
+
+/*
+ * Translate native file flags to Linux open flags.
+ */
+int
+lxpr_open_flags_convert(offset_t uf_flag, uint32_t f_flag)
+{
+ int flags = 0;
+
+ switch (f_flag & (FREAD | FWRITE)) {
+ case FREAD:
+ flags = LX_O_RDONLY;
+ break;
+ case FWRITE:
+ flags = LX_O_WRONLY;
+ break;
+ case FREAD | FWRITE:
+ flags = LX_O_RDWR;
+ break;
+ }
+
+ if (f_flag & FNDELAY)
+ flags |= LX_O_NDELAY;
+ if (f_flag & FAPPEND)
+ flags |= LX_O_APPEND;
+ if (f_flag & FSYNC)
+ flags |= LX_O_SYNC;
+ if (f_flag & FNONBLOCK)
+ flags |= LX_O_NONBLOCK;
+
+ if (f_flag & FCREAT)
+ flags |= LX_O_CREAT;
+ if (f_flag & FTRUNC)
+ flags |= LX_O_TRUNC;
+ if (f_flag & FEXCL)
+ flags |= LX_O_EXCL;
+ if (f_flag & FASYNC)
+ flags |= LX_O_ASYNC;
+ if (f_flag & FOFFMAX)
+ flags |= LX_O_LARGEFILE;
+ if (f_flag & FNOCTTY)
+ flags |= LX_O_NOCTTY;
+ if (f_flag & FNOFOLLOW)
+ flags |= LX_O_NOFOLLOW;
+
+ if (f_flag & FDIRECT)
+ flags |= LX_O_DIRECT;
+ if (f_flag & __FLXPATH)
+ flags |= LX_O_PATH;
+
+ if (uf_flag & FD_CLOEXEC)
+ flags |= LX_O_CLOEXEC;
+
+ return (flags);
+}
+
+/*
+ * Translate a Linux core_pattern path to a native illumos one, by replacing
* the appropriate % escape sequences.
*
* Any % escape sequences that are not recognised are double-escaped so that
@@ -854,7 +1003,7 @@ lxpr_core_path_l2s(const char *inp, char *outp, size_t outsz)
}
/*
- * Translate an Illumos core pattern path back to Linux format.
+ * Translate an illumos core pattern path back to Linux format.
*/
int
lxpr_core_path_s2l(const char *inp, char *outp, size_t outsz)
diff --git a/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c b/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c
index d573825652..6d4d2357eb 100644
--- a/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c
+++ b/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c
@@ -22,18 +22,11 @@
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2019 Joyent, Inc.
- * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
+ * Copyright 2021 OmniOS Community Edition (OmniOSce) Association.
*/
/*
* lx_proc -- a Linux-compatible /proc for the LX brand
- *
- * We have -- confusingly -- two implementations of Linux /proc. One is to
- * support native (but Linux-borne) programs that wish to view the native
- * system through the Linux /proc model; the other -- this one -- is to
- * support Linux binaries via the LX brand. These two implementations differ
- * greatly in their aspirations (and their willingness to bend the truth
- * of the system to accommodate those aspirations); they should not be unified.
*/
#include <sys/cpupart.h>
@@ -136,6 +129,7 @@ static vnode_t *lxpr_lookup_procdir(vnode_t *, char *);
static vnode_t *lxpr_lookup_piddir(vnode_t *, char *);
static vnode_t *lxpr_lookup_not_a_dir(vnode_t *, char *);
static vnode_t *lxpr_lookup_fddir(vnode_t *, char *);
+static vnode_t *lxpr_lookup_fdinfodir(vnode_t *, char *);
static vnode_t *lxpr_lookup_netdir(vnode_t *, char *);
static vnode_t *lxpr_lookup_sysdir(vnode_t *, char *);
static vnode_t *lxpr_lookup_sys_fsdir(vnode_t *, char *);
@@ -153,6 +147,7 @@ static int lxpr_readdir_procdir(lxpr_node_t *, uio_t *, int *);
static int lxpr_readdir_piddir(lxpr_node_t *, uio_t *, int *);
static int lxpr_readdir_not_a_dir(lxpr_node_t *, uio_t *, int *);
static int lxpr_readdir_fddir(lxpr_node_t *, uio_t *, int *);
+static int lxpr_readdir_fdinfodir(lxpr_node_t *, uio_t *, int *);
static int lxpr_readdir_netdir(lxpr_node_t *, uio_t *, int *);
static int lxpr_readdir_sysdir(lxpr_node_t *, uio_t *, int *);
static int lxpr_readdir_sys_fsdir(lxpr_node_t *, uio_t *, int *);
@@ -175,6 +170,7 @@ static void lxpr_read_devices(lxpr_node_t *, lxpr_uiobuf_t *);
static void lxpr_read_diskstats(lxpr_node_t *, lxpr_uiobuf_t *);
static void lxpr_read_isdir(lxpr_node_t *, lxpr_uiobuf_t *);
static void lxpr_read_fd(lxpr_node_t *, lxpr_uiobuf_t *);
+static void lxpr_read_fdinfo(lxpr_node_t *, lxpr_uiobuf_t *);
static void lxpr_read_filesystems(lxpr_node_t *, lxpr_uiobuf_t *);
static void lxpr_read_kmsg(lxpr_node_t *, lxpr_uiobuf_t *, ldi_handle_t);
static void lxpr_read_loadavg(lxpr_node_t *, lxpr_uiobuf_t *);
@@ -425,6 +421,7 @@ static lxpr_dirent_t piddir[] = {
{ LXPR_PID_STATUS, "status" },
{ LXPR_PID_TASKDIR, "task" },
{ LXPR_PID_FDDIR, "fd" },
+ { LXPR_PID_FDINFODIR, "fdinfo" },
{ LXPR_PID_UIDMAP, "uid_map" }
};
@@ -455,6 +452,7 @@ static lxpr_dirent_t tiddir[] = {
{ LXPR_PID_STATM, "statm" },
{ LXPR_PID_TID_STATUS, "status" },
{ LXPR_PID_FDDIR, "fd" },
+ { LXPR_PID_FDINFODIR, "fdinfo" },
{ LXPR_PID_UIDMAP, "uid_map" }
};
@@ -793,7 +791,6 @@ lxpr_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
/*
* lxpr_close(): Vnode operation for VOP_CLOSE()
*/
-/* ARGSUSED */
static int
lxpr_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
caller_context_t *ct)
@@ -844,6 +841,8 @@ static void (*lxpr_read_function[])() = {
lxpr_read_isdir, /* /proc/<pid>/task/nn */
lxpr_read_isdir, /* /proc/<pid>/fd */
lxpr_read_fd, /* /proc/<pid>/fd/nn */
+ lxpr_read_isdir, /* /proc/<pid>/fdinfo */
+ lxpr_read_fdinfo, /* /proc/<pid>/fdinfo/nn */
lxpr_read_pid_id_map, /* /proc/<pid>/uid_map */
lxpr_read_pid_auxv, /* /proc/<pid>/task/<tid>/auxv */
lxpr_read_pid_cgroup, /* /proc/<pid>/task/<tid>/cgroup */
@@ -867,6 +866,8 @@ static void (*lxpr_read_function[])() = {
lxpr_read_pid_tid_status, /* /proc/<pid>/task/<tid>/status */
lxpr_read_isdir, /* /proc/<pid>/task/<tid>/fd */
lxpr_read_fd, /* /proc/<pid>/task/<tid>/fd/nn */
+ lxpr_read_isdir, /* /proc/<pid>/task/<tid>/fdinfo */
+ lxpr_read_fdinfo, /* /proc/<pid>/task/<tid>/fdinfo/nn */
lxpr_read_pid_id_map, /* /proc/<pid>/task/<tid>/uid_map */
lxpr_read_cgroups, /* /proc/cgroups */
lxpr_read_cmdline, /* /proc/cmdline */
@@ -1014,6 +1015,8 @@ static vnode_t *(*lxpr_lookup_function[])() = {
lxpr_lookup_task_tid_dir, /* /proc/<pid>/task/nn */
lxpr_lookup_fddir, /* /proc/<pid>/fd */
lxpr_lookup_not_a_dir, /* /proc/<pid>/fd/nn */
+ lxpr_lookup_fdinfodir, /* /proc/<pid>/fdinfo */
+ lxpr_lookup_not_a_dir, /* /proc/<pid>/fdinfo/nn */
lxpr_lookup_not_a_dir, /* /proc/<pid>/uid_map */
lxpr_lookup_not_a_dir, /* /proc/<pid>/task/<tid>/auxv */
lxpr_lookup_not_a_dir, /* /proc/<pid>/task/<tid>/cgroup */
@@ -1037,6 +1040,8 @@ static vnode_t *(*lxpr_lookup_function[])() = {
lxpr_lookup_not_a_dir, /* /proc/<pid>/task/<tid>/status */
lxpr_lookup_fddir, /* /proc/<pid>/task/<tid>/fd */
lxpr_lookup_not_a_dir, /* /proc/<pid>/task/<tid>/fd/nn */
+ lxpr_lookup_fdinfodir, /* /proc/<pid>/task/<tid>/fdinfo */
+ lxpr_lookup_not_a_dir, /* /proc/<pid>/task/<tid>/fdinfo/nn */
lxpr_lookup_not_a_dir, /* /proc/<pid>/task/<tid>/uid_map */
lxpr_lookup_not_a_dir, /* /proc/cgroups */
lxpr_lookup_not_a_dir, /* /proc/cmdline */
@@ -1184,6 +1189,8 @@ static int (*lxpr_readdir_function[])() = {
lxpr_readdir_task_tid_dir, /* /proc/<pid>/task/nn */
lxpr_readdir_fddir, /* /proc/<pid>/fd */
lxpr_readdir_not_a_dir, /* /proc/<pid>/fd/nn */
+ lxpr_readdir_fdinfodir, /* /proc/<pid>/fdinfo */
+ lxpr_readdir_not_a_dir, /* /proc/<pid>/fdinfo/nn */
lxpr_readdir_not_a_dir, /* /proc/<pid>/uid_map */
lxpr_readdir_not_a_dir, /* /proc/<pid>/task/<tid>/auxv */
lxpr_readdir_not_a_dir, /* /proc/<pid>/task/<tid>/cgroup */
@@ -1207,6 +1214,8 @@ static int (*lxpr_readdir_function[])() = {
lxpr_readdir_not_a_dir, /* /proc/<pid>/task/<tid>/status */
lxpr_readdir_fddir, /* /proc/<pid>/task/<tid>/fd */
lxpr_readdir_not_a_dir, /* /proc/<pid>/task/<tid>/fd/nn */
+ lxpr_readdir_fdinfodir, /* /proc/<pid>/task/<tid>/fdinfo */
+ lxpr_readdir_not_a_dir, /* /proc/<pid>/task/<tid>/fdinfo/nn */
lxpr_readdir_not_a_dir, /* /proc/<pid>/task/<tid>/uid_map */
lxpr_readdir_not_a_dir, /* /proc/cgroups */
lxpr_readdir_not_a_dir, /* /proc/cmdline */
@@ -1331,7 +1340,6 @@ CTASSERT(ARRAY_SIZE(lxpr_readdir_function) == LXPR_NFILES);
* (at least in general, and certainly the difference is unlikely to be enough
* to justify have different routines for 32 and 64 bit reads
*/
-/* ARGSUSED */
static int
lxpr_read(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr,
caller_context_t *ct)
@@ -1393,21 +1401,18 @@ lxpr_read(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr,
* - empty file
* - wait to be able to read a file that will never have anything to read
*/
-/* ARGSUSED */
static void
lxpr_read_isdir(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
lxpr_uiobuf_seterr(uiobuf, EISDIR);
}
-/* ARGSUSED */
static void
lxpr_read_invalid(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
lxpr_uiobuf_seterr(uiobuf, EINVAL);
}
-/* ARGSUSED */
static void
lxpr_read_empty(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -1589,7 +1594,6 @@ lxpr_read_pid_tid_comm(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_printf(uiobuf, "%s\n", buf);
}
-/* ARGSUSED */
static int
lxpr_write_pid_tid_comm(lxpr_node_t *lxpnp, struct uio *uio, struct cred *cr,
caller_context_t *ct)
@@ -2238,6 +2242,58 @@ lxpr_enumerate_mounts(zone_t *zone)
return (result);
}
+static uint_t
+lxpr_get_mountid(zone_t *zone, vfs_t *match_vfsp)
+{
+ lx_zone_data_t *lxzd = ztolxzd(zone);
+ vfs_t *vfsp, *vfslist;
+ uint_t mount_id;
+
+ if (match_vfsp == NULL)
+ return (0);
+
+ /* Mount IDs start at 15 for the root, see lxpr_enumerate_mounts() */
+ mount_id = 15;
+
+ ASSERT(zone != global_zone);
+ ASSERT(lxzd != NULL);
+ ASSERT(lxzd->lxzd_vdisks != NULL);
+
+ if (zone->zone_rootvp->v_vfsp == match_vfsp)
+ return (mount_id);
+
+ vfs_list_read_lock();
+
+ vfsp = vfslist = zone->zone_vfslist;
+
+ do {
+ if (vfsp == zone->zone_rootvp->v_vfsp)
+ continue;
+
+ if (vfsp == NULL)
+ break;
+
+ /* Skip mounts we shouldn't show */
+ if ((vfsp->vfs_flag & VFS_NOMNTTAB) != 0) {
+ vfsp = vfsp->vfs_zone_next;
+ continue;
+ }
+
+ mount_id++;
+
+ if (vfsp == match_vfsp) {
+ vfs_list_unlock();
+ return (mount_id);
+ }
+
+ vfsp = vfsp->vfs_zone_next;
+ } while (vfsp != vfslist);
+
+ vfs_list_unlock();
+
+ return (0);
+}
+
/*
* lxpr_read_pid_mountinfo(): information about process mount points.
*/
@@ -2860,7 +2916,6 @@ lxpr_read_pid_tid_stat(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
cpu /* 39 */);
}
-/* ARGSUSED */
static void
lxpr_read_net_arp(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -3042,7 +3097,6 @@ lxpr_read_net_dev(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
kmem_free(ksr, sidx);
}
-/* ARGSUSED */
static void
lxpr_read_net_dev_mcast(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -3061,7 +3115,6 @@ lxpr_inet6_out(const in6_addr_t *addr, char buf[33])
buf[32] = '\0';
}
-/* ARGSUSED */
static void
lxpr_read_net_if_inet6(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -3102,19 +3155,16 @@ lxpr_read_net_if_inet6(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
netstack_rele(ns);
}
-/* ARGSUSED */
static void
lxpr_read_net_igmp(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
}
-/* ARGSUSED */
static void
lxpr_read_net_ip_mr_cache(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
}
-/* ARGSUSED */
static void
lxpr_read_net_ip_mr_vif(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -3159,7 +3209,6 @@ lxpr_format_route_ipv6(ire_t *ire, lxpr_uiobuf_t *uiobuf)
name);
}
-/* ARGSUSED */
static void
lxpr_read_net_ipv6_route(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -3180,19 +3229,16 @@ lxpr_read_net_ipv6_route(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
netstack_rele(ns);
}
-/* ARGSUSED */
static void
lxpr_read_net_mcfilter(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
}
-/* ARGSUSED */
static void
lxpr_read_net_netstat(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
}
-/* ARGSUSED */
static void
lxpr_read_net_raw(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -3222,7 +3268,7 @@ lxpr_format_route_ipv4(ire_t *ire, lxpr_uiobuf_t *uiobuf)
/*
* Search for a suitable IRE for naming purposes.
* On Linux, the default route is typically associated with the
- * interface used to access gateway. The default IRE on Illumos
+ * interface used to access gateway. The default IRE on illumos
* typically lacks an ill reference but its parent might have one.
*/
nire = ire;
@@ -3267,7 +3313,6 @@ lxpr_format_route_ipv4(ire_t *ire, lxpr_uiobuf_t *uiobuf)
ire->ire_metrics.iulp_rtt);
}
-/* ARGSUSED */
static void
lxpr_read_net_route(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -3291,19 +3336,16 @@ lxpr_read_net_route(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
netstack_rele(ns);
}
-/* ARGSUSED */
static void
lxpr_read_net_rpc(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
}
-/* ARGSUSED */
static void
lxpr_read_net_rt_cache(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
}
-/* ARGSUSED */
static void
lxpr_read_net_sockstat(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -3453,7 +3495,6 @@ lxpr_read_net_snmp(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
kmem_free(ksr, sidx);
}
-/* ARGSUSED */
static void
lxpr_read_net_stat(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -3861,7 +3902,6 @@ lxpr_read_net_unix(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
#define LX_KMSG_PRI "<0>"
-/* ARGSUSED */
static void
lxpr_read_kmsg(lxpr_node_t *lxpnp, struct lxpr_uiobuf *uiobuf, ldi_handle_t lh)
{
@@ -4052,7 +4092,6 @@ lxpr_read_meminfo(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
* Note: we currently also use this for /proc/{pid}/mounts since we don't
* yet support mount namespaces.
*/
-/* ARGSUSED */
static void
lxpr_read_mounts(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4130,7 +4169,6 @@ nextp:
* /proc/diskstats, and also because "fdisk -l" and a few other things look
* here to find all disks on the system.
*/
-/* ARGSUSED */
static void
lxpr_read_partitions(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4163,7 +4201,6 @@ lxpr_read_partitions(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
* the expected Linux major numbers. See lx devfs where some of the major
* numbers have no defined constants.
*/
-/* ARGSUSED */
static void
lxpr_read_devices(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4186,7 +4223,6 @@ lxpr_read_devices(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
* See the block comment above the per-device output-generating line for the
* details of the format.
*/
-/* ARGSUSED */
static void
lxpr_read_diskstats(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4315,7 +4351,6 @@ lxpr_read_diskstats(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
/*
* lxpr_read_version(): read the contents of the "version" file.
*/
-/* ARGSUSED */
static void
lxpr_read_version(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4350,7 +4385,6 @@ lxpr_read_version(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
version);
}
-/* ARGSUSED */
static void
lxpr_read_vmstat(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4405,7 +4439,6 @@ lxpr_read_vmstat(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
* lxpr_read_stat(): read the contents of the "stat" file.
*
*/
-/* ARGSUSED */
static void
lxpr_read_stat(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4603,7 +4636,6 @@ lxpr_read_stat(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
* It is important to use formatting identical to the Linux implementation
* so that consumers do not break. See swap_show() in mm/swapfile.c.
*/
-/* ARGSUSED */
static void
lxpr_read_swaps(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4636,7 +4668,6 @@ lxpr_read_swaps(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
}
}
-/* ARGSUSED */
static void
lxpr_read_sys_fs_aiomax(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4644,7 +4675,6 @@ lxpr_read_sys_fs_aiomax(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_printf(uiobuf, "%llu\n", LX_AIO_MAX_NR);
}
-/* ARGSUSED */
static void
lxpr_read_sys_fs_aionr(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4670,7 +4700,6 @@ lxpr_read_sys_fs_aionr(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
* (zone's proc limit) * (process.max-file-descriptor rctl privileged limit).
* The privileged rctl limit is the same as rlim_fd_max.
*/
-/* ARGSUSED */
static void
lxpr_read_sys_fs_filemax(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4694,7 +4723,6 @@ lxpr_read_sys_fs_filemax(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
* number of files in use within a zone, so we approximate that value by
* looking at the current "fi_nfiles" value for each process in the zone.
*/
-/* ARGSUSED */
static void
lxpr_read_sys_fs_filenr(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4742,7 +4770,6 @@ extern int inotify_maxevents;
extern int inotify_maxinstances;
extern int inotify_maxwatches;
-/* ARGSUSED */
static void
lxpr_read_sys_fs_inotify_max_queued_events(lxpr_node_t *lxpnp,
lxpr_uiobuf_t *uiobuf)
@@ -4751,7 +4778,6 @@ lxpr_read_sys_fs_inotify_max_queued_events(lxpr_node_t *lxpnp,
lxpr_uiobuf_printf(uiobuf, "%d\n", inotify_maxevents);
}
-/* ARGSUSED */
static void
lxpr_read_sys_fs_inotify_max_user_instances(lxpr_node_t *lxpnp,
lxpr_uiobuf_t *uiobuf)
@@ -4760,7 +4786,6 @@ lxpr_read_sys_fs_inotify_max_user_instances(lxpr_node_t *lxpnp,
lxpr_uiobuf_printf(uiobuf, "%d\n", inotify_maxinstances);
}
-/* ARGSUSED */
static void
lxpr_read_sys_fs_inotify_max_user_watches(lxpr_node_t *lxpnp,
lxpr_uiobuf_t *uiobuf)
@@ -4769,7 +4794,6 @@ lxpr_read_sys_fs_inotify_max_user_watches(lxpr_node_t *lxpnp,
lxpr_uiobuf_printf(uiobuf, "%d\n", inotify_maxwatches);
}
-/* ARGSUSED */
static void
lxpr_read_sys_fs_pipe_max(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4786,7 +4810,6 @@ lxpr_read_sys_fs_pipe_max(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_printf(uiobuf, "%u\n", pipe_max);
}
-/* ARGSUSED */
static void
lxpr_read_sys_kernel_caplcap(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4794,7 +4817,6 @@ lxpr_read_sys_kernel_caplcap(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_printf(uiobuf, "%d\n", LX_CAP_MAX_VALID);
}
-/* ARGSUSED */
static void
lxpr_read_sys_kernel_corepatt(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4837,7 +4859,6 @@ lxpr_read_sys_kernel_corepatt(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_printf(uiobuf, "%s\n", tr);
}
-/* ARGSUSED */
static void
lxpr_read_sys_kernel_hostname(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4845,7 +4866,6 @@ lxpr_read_sys_kernel_hostname(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_printf(uiobuf, "%s\n", uts_nodename());
}
-/* ARGSUSED */
static void
lxpr_read_sys_kernel_msgmax(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4862,7 +4882,6 @@ lxpr_read_sys_kernel_msgmax(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_printf(uiobuf, "%u\n", val);
}
-/* ARGSUSED */
static void
lxpr_read_sys_kernel_msgmnb(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4878,7 +4897,6 @@ lxpr_read_sys_kernel_msgmnb(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_printf(uiobuf, "%u\n", (uint_t)val);
}
-/* ARGSUSED */
static void
lxpr_read_sys_kernel_msgmni(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4894,7 +4912,6 @@ lxpr_read_sys_kernel_msgmni(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_printf(uiobuf, "%u\n", (uint_t)val);
}
-/* ARGSUSED */
static void
lxpr_read_sys_kernel_ngroups_max(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4902,7 +4919,6 @@ lxpr_read_sys_kernel_ngroups_max(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_printf(uiobuf, "%d\n", ngroups_max);
}
-/* ARGSUSED */
static void
lxpr_read_sys_kernel_osrel(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4920,7 +4936,6 @@ lxpr_read_sys_kernel_osrel(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_printf(uiobuf, "%s\n", version);
}
-/* ARGSUSED */
static void
lxpr_read_sys_kernel_pid_max(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -4983,7 +4998,6 @@ lxpr_read_sys_kernel_rand_bootid(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
/*
* The amount of entropy available (in bits).
*/
-/* ARGSUSED */
static void
lxpr_read_sys_kernel_rand_entavl(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5011,7 +5025,6 @@ lxpr_read_sys_kernel_rand_uuid(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_printf(uiobuf, "%s\n", uuid);
}
-/* ARGSUSED */
static void
lxpr_read_sys_kernel_sem(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5041,7 +5054,6 @@ lxpr_read_sys_kernel_sem(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
vmsl, vmns, vopm, vmni);
}
-/* ARGSUSED */
static void
lxpr_read_sys_kernel_shmall(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5058,7 +5070,6 @@ lxpr_read_sys_kernel_shmall(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_printf(uiobuf, "%u\n", (uint_t)btop(val));
}
-/* ARGSUSED */
static void
lxpr_read_sys_kernel_shmmax(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5077,7 +5088,6 @@ lxpr_read_sys_kernel_shmmax(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_printf(uiobuf, "%u\n", (uint_t)val);
}
-/* ARGSUSED */
static void
lxpr_read_sys_kernel_shmmni(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5096,7 +5106,6 @@ lxpr_read_sys_kernel_shmmni(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_printf(uiobuf, "%u\n", (uint_t)val);
}
-/* ARGSUSED */
static void
lxpr_read_sys_kernel_threads_max(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5104,7 +5113,6 @@ lxpr_read_sys_kernel_threads_max(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_printf(uiobuf, "%d\n", LXPTOZ(lxpnp)->zone_nlwps_ctl);
}
-/* ARGSUSED */
static void
lxpr_read_sys_net_core_somaxc(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5135,7 +5143,6 @@ lxpr_read_sys_net_core_somaxc(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
*
* Note that the Linux setting is the inverse of the illumos value.
*/
-/* ARGSUSED */
static void
lxpr_read_sys_net_ipv4_icmp_eib(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5165,7 +5172,6 @@ lxpr_read_sys_net_ipv4_icmp_eib(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
* in lx at this time, thus we do not support Linux-ABI methods for
* enabling/disabling forwarding, and this is always 0.
*/
-/* ARGSUSED */
static void
lxpr_read_sys_net_ipv4_ip_forward(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5182,7 +5188,6 @@ lxpr_read_sys_net_ipv4_ip_forward(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
* illumos: tcp_smallest_anon_port & tcp_largest_anon_port
* Not in tcp(7p) man page.
*/
-/* ARGSUSED */
static void
lxpr_read_sys_net_ipv4_ip_lport_range(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5259,7 +5264,6 @@ lxpr_read_sys_net_ipv4_tcp_cc_curr(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
* in the tcp_input_data() function on the use of tcp_fin_wait_2_flush_interval.
* The value is in milliseconds.
*/
-/* ARGSUSED */
static void
lxpr_read_sys_net_ipv4_tcp_fin_to(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5293,7 +5297,6 @@ lxpr_read_sys_net_ipv4_tcp_fin_to(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
* 9 times (giving a total of 11.25 minutes) so we emulate this by dividing out
* tcps_keepalive_abort_interval by 9.
*/
-/* ARGSUSED */
static void
lxpr_read_sys_net_ipv4_tcp_ka_int(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5324,7 +5327,6 @@ lxpr_read_sys_net_ipv4_tcp_ka_int(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
* The interval for sending out the first probe in milliseconds. The default is
* two hours.
*/
-/* ARGSUSED */
static void
lxpr_read_sys_net_ipv4_tcp_ka_tim(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5353,7 +5355,6 @@ lxpr_read_sys_net_ipv4_tcp_ka_tim(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
*
* illumos: tcp_conn_req_max_q0
*/
-/* ARGSUSED */
static void
lxpr_read_sys_net_ipv4_tcp_max_syn_bl(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5396,7 +5397,6 @@ lxpr_read_sys_net_ipv4_tcp_max_syn_bl(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
* The interval_max value is the maximum RTO in ms.
* The extra value is an extra time (in ms) to add in to the RTO.
*/
-/* ARGSUSED */
static void
lxpr_read_sys_net_ipv4_tcp_retry2(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5436,7 +5436,6 @@ lxpr_read_sys_net_ipv4_tcp_retry2(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
* tcp_xmit_hiwat is the default TCP send window size
* tcp_max_buf is the maximum TCP send and receive buffer size
*/
-/* ARGSUSED */
static void
lxpr_read_sys_net_ipv4_tcp_rwmem(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5476,7 +5475,6 @@ lxpr_read_sys_net_ipv4_tcp_rwmem(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
* tcp_sack_permitted 0 == disabled, 1 == no initiate but accept,
* 2 == initiate and accept. default is 2.
*/
-/* ARGSUSED */
static void
lxpr_read_sys_net_ipv4_tcp_sack(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5509,7 +5507,6 @@ lxpr_read_sys_net_ipv4_tcp_sack(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
* window scale option will be set only if the user has requested a send or
* receive window larger than 64K. The default value of is 1.
*/
-/* ARGSUSED */
static void
lxpr_read_sys_net_ipv4_tcp_winscale(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5573,7 +5570,6 @@ lxpr_read_sys_vm_dirty(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_printf(uiobuf, "%u\n", val);
}
-/* ARGSUSED */
static void
lxpr_read_sys_vm_max_map_cnt(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5582,7 +5578,6 @@ lxpr_read_sys_vm_max_map_cnt(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_printf(uiobuf, "%d\n", 16777215);
}
-/* ARGSUSED */
static void
lxpr_read_sys_vm_minfr_kb(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5590,7 +5585,6 @@ lxpr_read_sys_vm_minfr_kb(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_printf(uiobuf, "%d\n", 0);
}
-/* ARGSUSED */
static void
lxpr_read_sys_vm_nhpages(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5598,7 +5592,6 @@ lxpr_read_sys_vm_nhpages(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_printf(uiobuf, "%d\n", 0);
}
-/* ARGSUSED */
static void
lxpr_read_sys_vm_overcommit_mem(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5606,7 +5599,6 @@ lxpr_read_sys_vm_overcommit_mem(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_printf(uiobuf, "%d\n", 0);
}
-/* ARGSUSED */
static void
lxpr_read_sys_vm_swappiness(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5620,7 +5612,6 @@ lxpr_read_sys_vm_swappiness(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
* format is: "%.2lf, %.2lf",uptime_secs, idle_secs
* Use fixed point arithmetic to get 2 decimal places
*/
-/* ARGSUSED */
static void
lxpr_read_uptime(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -5685,7 +5676,6 @@ lxpr_read_uptime(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
* cgroup subsystems as being installed. The commented example below shows
* how to print a subsystem entry.
*/
-/* ARGSUSED */
static void
lxpr_read_cgroups(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -6000,7 +5990,6 @@ lx_cpuinfo_mapping_t lx_cpuinfo_mappings[] = {
#define LX_CPUINFO_MAPPING_MAX \
(sizeof (lx_cpuinfo_mappings) / sizeof (lx_cpuinfo_mappings[0]))
-/* ARGSUSED */
static void
lxpr_read_cpuinfo(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -6131,7 +6120,6 @@ lxpr_read_cpuinfo(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
mutex_exit(&cpu_lock);
}
-/* ARGSUSED */
static void
lxpr_read_fd(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -6139,12 +6127,71 @@ lxpr_read_fd(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
lxpr_uiobuf_seterr(uiobuf, EFAULT);
}
+static void
+lxpr_read_fdinfo(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
+{
+ zone_t *zone = LXPTOZ(lxpnp);
+ proc_t *p;
+ file_t *fp;
+ vnode_t *vp;
+ offset_t off;
+ short uf_flag;
+ int fd;
+
+ ASSERT(lxpnp->lxpr_type == LXPR_PID_FDINFO_FD);
+
+ p = lxpr_lock(lxpnp, NO_ZOMB);
+ if (p == NULL) {
+ lxpr_uiobuf_seterr(uiobuf, EINVAL);
+ return;
+ }
+
+ if ((p->p_flag & SSYS) || p->p_as == &kas) {
+ lxpr_uiobuf_seterr(uiobuf, EFAULT);
+ lxpr_unlock(p);
+ return;
+ }
+
+ fd = lxpnp->lxpr_desc;
+
+ fp = lxpr_getf(p, fd, &uf_flag);
+ if (fp == NULL) {
+ lxpr_uiobuf_seterr(uiobuf, ENOENT);
+ lxpr_unlock(p);
+ return;
+ }
+ vp = fp->f_vnode;
+
+ /*
+ * Check that the offset value in the underlying file_t is plausible
+ * and reset to 0 if not.
+ */
+ if (fp->f_offset == -1) {
+ off = 0;
+ } else {
+ off = fp->f_offset;
+ if (VOP_SEEK(vp, 0, &off, NULL) != 0)
+ off = 0;
+ }
+
+ lxpr_uiobuf_printf(uiobuf, "pos:\t%ld\n", off);
+ lxpr_uiobuf_printf(uiobuf, "flags:\t0%o\n",
+ lxpr_open_flags_convert(uf_flag,
+ fp->f_flag2 << 16 | fp->f_flag));
+ lxpr_uiobuf_printf(uiobuf, "mnt_id:\t%u\n",
+ lxpr_get_mountid(zone, vp->v_vfsp));
+
+ /* Could show additional fields based on vp->v_type */
+
+ lxpr_releasef(p, fd);
+ lxpr_unlock(p);
+}
+
/*
* Report a list of file systems loaded in the kernel. We only report the ones
* which we support and which may be checked by various components to see if
* they are loaded.
*/
-/* ARGSUSED */
static void
lxpr_read_filesystems(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
@@ -6269,6 +6316,10 @@ lxpr_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
*/
if ((flags & FOLLOW) == 0)
vap->va_type = VLNK;
+ case LXPR_PID_FDINFO_FD:
+ case LXPR_PID_TID_FDINFO_FD:
+ /* Linux leaves the file size for these as 0 */
+ break;
default:
break;
}
@@ -6401,7 +6452,6 @@ lxpr_doaccess(lxpr_node_t *lxpnp, boolean_t shallow, int mode, int flags,
return (EACCES);
}
-/* ARGSUSED */
static vnode_t *
lxpr_lookup_not_a_dir(vnode_t *dp, char *comp)
{
@@ -6411,7 +6461,6 @@ lxpr_lookup_not_a_dir(vnode_t *dp, char *comp)
/*
* lxpr_lookup(): Vnode operation for VOP_LOOKUP()
*/
-/* ARGSUSED */
static int
lxpr_lookup(vnode_t *dp, char *comp, vnode_t **vpp, pathname_t *pathp,
int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
@@ -6649,6 +6698,15 @@ lxpr_lookup_fddir(vnode_t *dp, char *comp)
}
static vnode_t *
+lxpr_lookup_fdinfodir(vnode_t *dp, char *comp)
+{
+ ASSERT(VTOLXP(dp)->lxpr_type == LXPR_PID_FDINFODIR ||
+ VTOLXP(dp)->lxpr_type == LXPR_PID_TID_FDINFODIR);
+
+ return (lxpr_lookup_fdinfonode(dp, comp));
+}
+
+static vnode_t *
lxpr_lookup_netdir(vnode_t *dp, char *comp)
{
ASSERT(VTOLXP(dp)->lxpr_type == LXPR_NETDIR);
@@ -6790,7 +6848,6 @@ lxpr_lookup_sys_fs_inotifydir(vnode_t *dp, char *comp)
/*
* lxpr_readdir(): Vnode operation for VOP_READDIR()
*/
-/* ARGSUSED */
static int
lxpr_readdir(vnode_t *dp, uio_t *uiop, cred_t *cr, int *eofp,
caller_context_t *ct, int flags)
@@ -6832,7 +6889,6 @@ lxpr_readdir(vnode_t *dp, uio_t *uiop, cred_t *cr, int *eofp,
return (lxpr_readdir_function[type](lxpnp, uiop, eofp));
}
-/* ARGSUSED */
static int
lxpr_readdir_not_a_dir(lxpr_node_t *lxpnp, uio_t *uiop, int *eofp)
{
@@ -7267,7 +7323,8 @@ lxpr_readdir_task_tid_dir(lxpr_node_t *lxpnp, uio_t *uiop, int *eofp)
}
static int
-lxpr_readdir_fddir(lxpr_node_t *lxpnp, uio_t *uiop, int *eofp)
+lxpr_readdir_fdlist(lxpr_node_t *lxpnp, uio_t *uiop, int *eofp,
+ lxpr_nodetype_t inodetype)
{
/* bp holds one dirent64 structure */
longlong_t bp[DIRENT64_RECLEN(LXPNSIZ) / sizeof (longlong_t)];
@@ -7279,8 +7336,13 @@ lxpr_readdir_fddir(lxpr_node_t *lxpnp, uio_t *uiop, int *eofp)
proc_t *p;
uf_info_t *fip;
- ASSERT(lxpnp->lxpr_type == LXPR_PID_FDDIR ||
- lxpnp->lxpr_type == LXPR_PID_TID_FDDIR);
+ ASSERT(
+ (inodetype == LXPR_PID_FD_FD && (
+ lxpnp->lxpr_type == LXPR_PID_FDDIR ||
+ lxpnp->lxpr_type == LXPR_PID_TID_FDDIR)) ||
+ (inodetype == LXPR_PID_FDINFO_FD && (
+ lxpnp->lxpr_type == LXPR_PID_FDINFODIR ||
+ lxpnp->lxpr_type == LXPR_PID_TID_FDINFODIR)));
oresid = uiop->uio_resid;
@@ -7345,7 +7407,7 @@ lxpr_readdir_fddir(lxpr_node_t *lxpnp, uio_t *uiop, int *eofp)
if (fip->fi_list[fd].uf_file == NULL)
continue;
- dirent->d_ino = lxpr_inode(LXPR_PID_FD_FD, p->p_pid, fd);
+ dirent->d_ino = lxpr_inode(inodetype, p->p_pid, fd);
len = snprintf(dirent->d_name, LXPNSIZ, "%d", fd);
ASSERT(len < LXPNSIZ);
reclen = DIRENT64_RECLEN(len);
@@ -7380,6 +7442,18 @@ out:
}
static int
+lxpr_readdir_fddir(lxpr_node_t *lxpnp, uio_t *uiop, int *eofp)
+{
+ return (lxpr_readdir_fdlist(lxpnp, uiop, eofp, LXPR_PID_FD_FD));
+}
+
+static int
+lxpr_readdir_fdinfodir(lxpr_node_t *lxpnp, uio_t *uiop, int *eofp)
+{
+ return (lxpr_readdir_fdlist(lxpnp, uiop, eofp, LXPR_PID_FDINFO_FD));
+}
+
+static int
lxpr_readdir_sysdir(lxpr_node_t *lxpnp, uio_t *uiop, int *eofp)
{
ASSERT(lxpnp->lxpr_type == LXPR_SYSDIR);
@@ -7491,7 +7565,6 @@ lxpr_tokenize_num(char *str, long *pv, char **ep)
return (0);
}
-/* ARGSUSED */
static int
lxpr_write_tcp_property(lxpr_node_t *lxpnp, struct uio *uio,
struct cred *cr, caller_context_t *ct, char *prop,
@@ -7644,7 +7717,6 @@ lxpr_xlate_sack(char *val, int size)
* We're updating a property on the ip stack so we can't reuse
* lxpr_write_tcp_property.
*/
-/* ARGSUSED */
static int
lxpr_write_sys_net_ipv4_icmp_eib(lxpr_node_t *lxpnp, struct uio *uio,
struct cred *cr, caller_context_t *ct)
@@ -7702,7 +7774,6 @@ lxpr_write_sys_net_ipv4_icmp_eib(lxpr_node_t *lxpnp, struct uio *uio,
* set two properties on the netstack_tcp, so we can't reuse
* lxpr_write_tcp_property.
*/
-/* ARGSUSED */
static int
lxpr_write_sys_net_ipv4_ip_lport_range(lxpr_node_t *lxpnp, struct uio *uio,
struct cred *cr, caller_context_t *ct)
@@ -7785,7 +7856,6 @@ lxpr_write_sys_net_ipv4_ip_lport_range(lxpr_node_t *lxpnp, struct uio *uio,
*
* See the Linux tcp(7) man page.
*/
-/* ARGSUSED */
static int
lxpr_write_sys_net_ipv4_tcp_rwmem(lxpr_node_t *lxpnp, struct uio *uio,
struct cred *cr, caller_context_t *ct)
@@ -7952,7 +8022,6 @@ lxpr_write_sys_net_ipv4_tcp_winscale(lxpr_node_t *lxpnp, struct uio *uio,
NULL));
}
-/* ARGSUSED */
static int
lxpr_write_sys_fs_pipe_max(lxpr_node_t *lxpnp, struct uio *uio,
struct cred *cr, caller_context_t *ct)
@@ -8005,7 +8074,6 @@ lxpr_write_sys_fs_pipe_max(lxpr_node_t *lxpnp, struct uio *uio,
return (0);
}
-/* ARGSUSED */
static int
lxpr_write_sys_kernel_corepatt(lxpr_node_t *lxpnp, struct uio *uio,
struct cred *cr, caller_context_t *ct)
@@ -8066,7 +8134,6 @@ lxpr_write_sys_kernel_corepatt(lxpr_node_t *lxpnp, struct uio *uio,
return (0);
}
-/* ARGSUSED */
static int
lxpr_write_pid_loginuid(lxpr_node_t *lxpnp, struct uio *uio, struct cred *cr,
caller_context_t *ct)
@@ -8167,12 +8234,11 @@ lxpr_readlink_exe(lxpr_node_t *lxpnp, char *buf, size_t size, cred_t *cr)
/*
* lxpr_readlink(): Vnode operation for VOP_READLINK()
*/
-/* ARGSUSED */
static int
lxpr_readlink(vnode_t *vp, uio_t *uiop, cred_t *cr, caller_context_t *ct)
{
- char bp[MAXPATHLEN + 1];
- size_t buflen = sizeof (bp);
+ char *bp;
+ size_t buflen, klen;
lxpr_node_t *lxpnp = VTOLXP(vp);
vnode_t *rvp = lxpnp->lxpr_realvp;
pid_t pid;
@@ -8199,11 +8265,14 @@ lxpr_readlink(vnode_t *vp, uio_t *uiop, cred_t *cr, caller_context_t *ct)
if (vp->v_type != VLNK && lxpnp->lxpr_type != LXPR_PID_FD_FD)
return (EINVAL);
+ buflen = klen = MAXPATHLEN + 1;
+ bp = kmem_alloc(klen, KM_SLEEP);
+
/* Try to produce a symlink name for anything that has a realvp */
if (rvp != NULL) {
error = lxpr_doaccess(lxpnp, B_TRUE, VREAD, 0, cr, ct);
if (error != 0)
- return (error);
+ goto out;
error = vnodetopath(NULL, rvp, bp, buflen, cr);
@@ -8221,7 +8290,7 @@ lxpr_readlink(vnode_t *vp, uio_t *uiop, cred_t *cr, caller_context_t *ct)
*/
if (lxpnp->lxpr_type != LXPR_PID_FD_FD ||
lxpr_readlink_fdnode(lxpnp, bp, buflen) != 0) {
- return (error);
+ goto out;
}
}
} else {
@@ -8239,18 +8308,24 @@ lxpr_readlink(vnode_t *vp, uio_t *uiop, cred_t *cr, caller_context_t *ct)
case LXPR_PID_CURDIR:
case LXPR_PID_ROOTDIR:
case LXPR_PID_EXE:
- return (EACCES);
+ error = EACCES;
+ goto out;
default:
/*
* Need to return error so that nothing thinks
* that the symlink is empty and hence "."
*/
- return (EINVAL);
+ error = EINVAL;
+ goto out;
}
}
/* copy the link data to user space */
- return (uiomove(bp, strlen(bp), UIO_READ, uiop));
+ error = uiomove(bp, strlen(bp), UIO_READ, uiop);
+
+out:
+ kmem_free(bp, klen);
+ return (error);
}
@@ -8259,7 +8334,6 @@ lxpr_readlink(vnode_t *vp, uio_t *uiop, cred_t *cr, caller_context_t *ct)
* Vnode is no longer referenced, deallocate the file
* and all its resources.
*/
-/* ARGSUSED */
static void
lxpr_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
{
@@ -8322,7 +8396,6 @@ lxpr_realvp(vnode_t *vp, vnode_t **vpp, caller_context_t *ct)
/* Pollhead for fake POLLET support below */
static struct pollhead lxpr_pollhead;
-/* ARGSUSED */
static int
lxpr_poll(vnode_t *vp, short ev, int anyyet, short *reventsp,
pollhead_t **phpp, caller_context_t *ct)
@@ -8358,7 +8431,6 @@ lxpr_poll(vnode_t *vp, short ev, int anyyet, short *reventsp,
return (0);
}
-/* ARGSUSED */
static int
lxpr_write(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr,
caller_context_t *ct)
@@ -8383,7 +8455,6 @@ lxpr_write(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr,
}
/* Needed for writable files which are first "truncated" */
-/* ARGSUSED */
static int
lxpr_space(vnode_t *vp, int cmd, flock64_t *bfp, int flag, offset_t offset,
cred_t *cred, caller_context_t *ct)
@@ -8402,7 +8473,6 @@ lxpr_space(vnode_t *vp, int cmd, flock64_t *bfp, int flag, offset_t offset,
* Needed for writable files which are first "truncated". We only support
* truncation.
*/
-/* ARGSUSED */
static int
lxpr_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
caller_context_t *ct)
@@ -8420,7 +8490,6 @@ lxpr_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
/*
* We need to allow open with O_CREAT for the writable files.
*/
-/* ARGSUSED */
static int
lxpr_create(vnode_t *dvp, char *nm, vattr_t *vap, enum vcexcl exclusive,
int mode, vnode_t **vpp, cred_t *cr, int flag, caller_context_t *ct,
diff --git a/usr/src/uts/common/brand/lx/syscall/lx_mount.c b/usr/src/uts/common/brand/lx/syscall/lx_mount.c
index 2524e9044a..fff6c81339 100644
--- a/usr/src/uts/common/brand/lx/syscall/lx_mount.c
+++ b/usr/src/uts/common/brand/lx/syscall/lx_mount.c
@@ -118,6 +118,7 @@ static mount_opt_t lx_tmpfs_options[] = {
{ "mode", MOUNT_OPT_UINT },
{ "uid", MOUNT_OPT_UINT },
{ "gid", MOUNT_OPT_UINT },
+ { "nr_inodes", MOUNT_OPT_PASSTHRU },
{ NULL, MOUNT_OPT_INVALID }
};
@@ -312,7 +313,8 @@ lx_mnt_opt_rm(char *opts, char *rmopt, char *retstr, int retlen)
ASSERT((opts != NULL) && (rmopt != NULL));
- retstr[0] = '\0';
+ if (retstr != NULL)
+ retstr[0] = '\0';
/* If no options were specified, there's no problem. */
if (opts_len == 0)
@@ -324,12 +326,13 @@ lx_mnt_opt_rm(char *opts, char *rmopt, char *retstr, int retlen)
for (optend = optstart; *optend != ',' && *optend != '\0'; optend++)
;
- /*LINTED*/
optlen = optend - optstart;
- if (optlen >= retlen)
- return (-1);
- (void) strncpy(retstr, optstart, optlen);
- retstr[optlen] = '\0';
+ if (retstr != NULL) {
+ if (optlen >= retlen)
+ return (-1);
+ (void) strncpy(retstr, optstart, optlen);
+ retstr[optlen] = '\0';
+ }
if (*optend == ',')
optend++;
@@ -414,9 +417,8 @@ lx_mount(const char *sourcep, const char *targetp, const char *fstypep,
uint_t flags, const void *datap)
{
char fstype[16];
- char source[MAXPATHLEN];
- char target[MAXPATHLEN];
- char options[MAX_MNTOPT_STR];
+ char *source, *target, *options;
+ size_t sourcel, targetl, optionsl;
int sflags, rv;
struct mounta ma, *map = &ma;
vfs_t *vfsp;
@@ -452,15 +454,25 @@ lx_mount(const char *sourcep, const char *targetp, const char *fstypep,
return (0);
}
+ /* Make sure we support the requested mount flags. */
+ if ((flags & ~LX_MS_SUPPORTED) != 0)
+ return (set_errno(ENOTSUP));
+
+ sourcel = targetl = MAXPATHLEN;
+ optionsl = MAX_MNTOPT_STR;
+ source = kmem_alloc(sourcel, KM_SLEEP);
+ target = kmem_alloc(targetl, KM_SLEEP);
+ options = kmem_alloc(optionsl, KM_SLEEP);
+
sflags = MS_SYSSPACE | MS_OPTIONSTR;
options[0] = '\0';
/* Copy in parameters that are always present. */
- if ((rv = lx_mnt_copyin_arg(sourcep, source, sizeof (source))) != 0)
- return (set_errno(rv));
+ if ((rv = lx_mnt_copyin_arg(sourcep, source, sourcel)) != 0)
+ goto out;
- if ((rv = lx_mnt_copyin_arg(targetp, target, sizeof (target))) != 0)
- return (set_errno(rv));
+ if ((rv = lx_mnt_copyin_arg(targetp, target, targetl)) != 0)
+ goto out;
/*
* While SunOS is picky about mount(2) target paths being absolute,
@@ -468,26 +480,62 @@ lx_mount(const char *sourcep, const char *targetp, const char *fstypep,
* requirement we must lookup the full path.
*/
if (target[0] != '/') {
- vnode_t *vp;
-
- if ((rv = lookupnameatcred(target, UIO_SYSSPACE, FOLLOW,
- NULLVPP, &vp, NULL, CRED())) != 0)
- return (set_errno(rv));
+ if ((rv = lookupname(target, UIO_SYSSPACE, FOLLOW,
+ NULLVPP, &vp)) != 0) {
+ goto out;
+ }
- rv = vnodetopath(NULL, vp, target, MAXPATHLEN, CRED());
+ rv = vnodetopath(NULL, vp, target, targetl, CRED());
VN_RELE(vp);
if (rv != 0)
- return (set_errno(rv));
+ goto out;
}
- /* Make sure we support the requested mount flags. */
- if ((flags & ~LX_MS_SUPPORTED) != 0)
- return (set_errno(ENOTSUP));
+ /*
+ * Following commits* in September 2020, systemd mounts most
+ * filesystems via an open file descriptor in order to avoid
+ * following mount point symlinks.
+ * It does this by opening the mount point with O_NOFOLLOW|O_PATH
+ * and then performing the mount on /proc/self/fd/<fd>.
+ * In illumos, this results in a mount attempt on the lx_proc vnode
+ * instead of the intended mount point, which fails since /proc files
+ * are generally marked as unmountable (and we wouldn't want this
+ * anyway).
+ * As a workaround, the /proc vnode's link target is retrieved and
+ * used for mount. This lookup causes procfs to return the path of
+ * the vnode's realvp which is the path of the underlying directory.
+ * Additonally, since systemd is holding an open file descriptor for
+ * the mount point, overlay mounts also need to be allowed.
+ *
+ * * https://github.com/systemd/systemd/commit/28126409b20bca9aa6f
+ * * https://github.com/systemd/systemd/commit/21935150a0c42b91a32
+ */
+ if (strncmp(target, "/proc/self/fd/", 14) == 0 &&
+ lookupname(target, UIO_SYSSPACE, NO_FOLLOW, NULLVPP, &vp) == 0) {
+ struct iovec iov = {0};
+ struct uio uio = {0};
+
+ iov.iov_base = target;
+ iov.iov_len = targetl;
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_resid = targetl;
+ uio.uio_segflg = UIO_SYSSPACE;
+ uio.uio_llimit = MAXOFFSET_T;
+
+ rv = VOP_READLINK(vp, &uio, CRED(), NULL);
+ VN_RELE(vp);
+ if (rv != 0)
+ goto out;
+ target[targetl - uio.uio_resid] = '\0';
+ sflags |= MS_OVERLAY;
+ }
/* Copy in Linux mount options. */
if (datap != NULL &&
- (rv = lx_mnt_copyin_arg(datap, options, sizeof (options))) != 0)
- return (set_errno(rv));
+ (rv = lx_mnt_copyin_arg(datap, options, optionsl)) != 0) {
+ goto out;
+ }
/* Do filesystem specific mount work. */
if (flags & LX_MS_BIND) {
@@ -496,44 +544,56 @@ lx_mount(const char *sourcep, const char *targetp, const char *fstypep,
/* Verify Linux mount options. */
if ((rv = lx_mnt_opt_verify(options, lofs_options)) != 0)
- return (set_errno(rv));
+ goto out;
} else if (strcmp(fstype, "tmpfs") == 0) {
char idstr[64];
/* Verify Linux mount options. */
if ((rv = lx_mnt_opt_verify(options, lx_tmpfs_options)) != 0)
- return (set_errno(rv));
+ goto out;
/*
* Linux defaults to mode=1777 for tmpfs mounts.
*/
if (strstr(options, "mode=") == NULL) {
if (options[0] != '\0')
- (void) strlcat(options, ",", sizeof (options));
- (void) strlcat(options, "mode=1777", sizeof (options));
+ (void) strlcat(options, ",", optionsl);
+ (void) strlcat(options, "mode=1777", optionsl);
}
+ /*
+ * Linux supports "nr_inodes=<val>" for tmpfs. There is no
+ * analogue in illumos - drop the option.
+ */
+ (void) lx_mnt_opt_rm(options, "nr_inodes=", NULL, 0);
+
switch (lx_mnt_opt_rm(options, "uid=", idstr, sizeof (idstr))) {
case 0:
uid = -1;
break;
case 1:
- if (lx_mnt_opt_val(idstr, &uid) < 0)
- return (set_errno(EINVAL));
+ if (lx_mnt_opt_val(idstr, &uid) < 0) {
+ rv = EINVAL;
+ goto out;
+ }
break;
default:
- return (set_errno(E2BIG));
+ rv = E2BIG;
+ goto out;
}
switch (lx_mnt_opt_rm(options, "gid=", idstr, sizeof (idstr))) {
case 0:
gid = -1;
break;
case 1:
- if (lx_mnt_opt_val(idstr, &gid) < 0)
- return (set_errno(EINVAL));
+ if (lx_mnt_opt_val(idstr, &gid) < 0) {
+ rv = EINVAL;
+ goto out;
+ }
break;
default:
- return (set_errno(E2BIG));
+ rv = E2BIG;
+ goto out;
}
/*
@@ -550,14 +610,14 @@ lx_mount(const char *sourcep, const char *targetp, const char *fstypep,
/* Verify Linux mount options. */
if ((rv = lx_mnt_opt_verify(options, lx_proc_options)) != 0)
- return (set_errno(rv));
+ goto out;
} else if (strcmp(fstype, "sysfs") == 0) {
/* Translate sysfs mount requests to lx_sysfs requests. */
(void) strcpy(fstype, "lx_sysfs");
/* Verify Linux mount options. */
if ((rv = lx_mnt_opt_verify(options, lx_sysfs_options)) != 0)
- return (set_errno(rv));
+ goto out;
} else if (strcmp(fstype, "cgroup") == 0) {
/* Translate cgroup mount requests to lx_cgroup requests. */
(void) strcpy(fstype, "lx_cgroup");
@@ -572,7 +632,7 @@ lx_mount(const char *sourcep, const char *targetp, const char *fstypep,
/* Verify Linux mount options. */
if ((rv = lx_mnt_opt_verify(options, lx_autofs_options)) != 0)
- return (set_errno(rv));
+ goto out;
/* Linux seems to always allow overlay mounts */
sflags |= MS_OVERLAY;
@@ -599,23 +659,27 @@ lx_mount(const char *sourcep, const char *targetp, const char *fstypep,
flags &= ~(LX_MS_RELATIME | LX_MS_NOATIME);
}
if ((flags & LX_MS_NODEV) &&
- (rv = lx_mnt_add_opt("nodev", options, sizeof (options))) != 0)
- return (set_errno(rv));
+ (rv = lx_mnt_add_opt("nodev", options, optionsl)) != 0) {
+ goto out;
+ }
if ((flags & LX_MS_NOEXEC) &&
- (rv = lx_mnt_add_opt("noexec", options, sizeof (options))) != 0)
- return (set_errno(rv));
+ (rv = lx_mnt_add_opt("noexec", options, optionsl)) != 0) {
+ goto out;
+ }
if ((flags & LX_MS_NOATIME) &&
- (rv = lx_mnt_add_opt("noatime", options, sizeof (options))) != 0)
- return (set_errno(rv));
+ (rv = lx_mnt_add_opt("noatime", options, optionsl)) != 0) {
+ goto out;
+ }
if ((rv = lookupname(target, UIO_SYSSPACE, FOLLOW, NULLVPP, &vp)) != 0)
- return (set_errno(rv));
+ goto out;
/* If mounting proc over itself, just return ok */
if (strcmp(fstype, "lx_proc") == 0 && strcmp("lx_proc",
vfssw[vp->v_vfsp->vfs_fstype].vsw_name) == 0) {
VN_RELE(vp);
- return (0);
+ rv = 0;
+ goto out;
}
map->spec = source;
@@ -625,12 +689,12 @@ lx_mount(const char *sourcep, const char *targetp, const char *fstypep,
map->dataptr = NULL;
map->datalen = 0;
map->optptr = options;
- map->optlen = sizeof (options);
+ map->optlen = optionsl;
rv = domount(NULL, map, vp, CRED(), &vfsp);
VN_RELE(vp);
if (rv != 0)
- return (set_errno(rv));
+ goto out;
VFS_RELE(vfsp);
if (strcmp(fstype, "tmpfs") == 0 && (uid != -1 || gid != -1)) {
@@ -642,7 +706,12 @@ lx_mount(const char *sourcep, const char *targetp, const char *fstypep,
}
}
- return (0);
+out:
+ kmem_free(source, sourcel);
+ kmem_free(target, targetl);
+ kmem_free(options, optionsl);
+
+ return (rv == 0 ? rv : set_errno(rv));
}
/*
diff --git a/usr/src/uts/common/brand/lx/syscall/lx_stat.c b/usr/src/uts/common/brand/lx/syscall/lx_stat.c
index 9af0080138..0f5460816b 100644
--- a/usr/src/uts/common/brand/lx/syscall/lx_stat.c
+++ b/usr/src/uts/common/brand/lx/syscall/lx_stat.c
@@ -393,7 +393,7 @@ lx_fstatat64(int fd, char *name, void *outp, int flag)
vnode_t *vp = NULL;
cred_t *cr = NULL;
model_t model = get_udatamodel();
- enum symfollow follow = FOLLOW;
+ int follow = FOLLOW;
int error;
char c;
@@ -403,18 +403,13 @@ lx_fstatat64(int fd, char *name, void *outp, int flag)
if ((flag & ~LX_FSTATAT_ALLOWED) != 0) {
return (set_errno(EINVAL));
}
- if ((flag & LX_AT_NO_AUTOMOUNT) != 0) {
- /*
- * While AT_NO_AUTOMOUNT is a legal flag for fstatat64, it is
- * not yet supported by lx_autofs.
- */
- lx_unsupported("fstatat(AT_NO_AUTOMOUNT)");
- return (set_errno(EINVAL));
- }
if ((flag & LX_AT_SYMLINK_NOFOLLOW) != 0) {
follow = NO_FOLLOW;
}
+ if ((flag & LX_AT_NO_AUTOMOUNT) != 0)
+ follow |= __FLXNOAUTO;
+
if (copyin(name, &c, sizeof (c)) != 0) {
return (set_errno(EFAULT));
}
diff --git a/usr/src/uts/common/fs/lookup.c b/usr/src/uts/common/fs/lookup.c
index 093db5a4b4..32a3d19708 100644
--- a/usr/src/uts/common/fs/lookup.c
+++ b/usr/src/uts/common/fs/lookup.c
@@ -246,6 +246,9 @@ lookuppnvp(
pp = &presrvd;
}
+ if (flags & __FLXNOAUTO)
+ lookup_flags |= __FLXNOAUTO;
+
if (auditing)
audit_anchorpath(pnp, vp == rootvp);
diff --git a/usr/src/uts/common/sys/file.h b/usr/src/uts/common/sys/file.h
index be96a68d46..66620ab7b9 100644
--- a/usr/src/uts/common/sys/file.h
+++ b/usr/src/uts/common/sys/file.h
@@ -125,6 +125,11 @@ typedef struct fpollinfo {
* Private interface for lx O_PATH|O_NOFOLLOW emulation for symlinks.
*/
#define __FLXPATH 0x80000000
+/*
+ * Private interface for lx fstatat(AT_NO_AUTOMOUNT) emulation.
+ * Since usage is disjoint, the __FLXPATH bit is re-used.
+ */
+#define __FLXNOAUTO 0x80000000
#if defined(_KERNEL) || defined(_FAKE_KERNEL)