Skip to content

Instantly share code, notes, and snippets.

@mgerdts
Last active December 31, 2017 05:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mgerdts/4ef21eb42d71f95e0c203466cc9564fb to your computer and use it in GitHub Desktop.
Save mgerdts/4ef21eb42d71f95e0c203466cc9564fb to your computer and use it in GitHub Desktop.
OS-XXX sdev plugin should not force number of the beast
commit efd2c605947a09c8c641ec66ec327082fa62f239
Author: Mike Gerdts <mike.gerdts@joyent.com>
Date: Sat Dec 30 05:18:57 2017 +0000
OS-XXX sdev plugin should not force number of the beast
diff --git a/usr/src/uts/common/fs/dev/sdev_plugin.c b/usr/src/uts/common/fs/dev/sdev_plugin.c
index dd81a52..58f7256 100644
--- a/usr/src/uts/common/fs/dev/sdev_plugin.c
+++ b/usr/src/uts/common/fs/dev/sdev_plugin.c
@@ -272,24 +272,29 @@ sdev_plugin_mknod(sdev_ctx_t ctx, char *name, mode_t mode, dev_t dev)
sdev_node_t *sdvp;
timestruc_t now;
struct vattr vap;
+ mode_t devmode = mode & (S_IFCHR | S_IFBLK);
if (sdev_plugin_name_isvalid(name, SDEV_PLUGIN_NAMELEN) == 0)
return (EINVAL);
sdvp = (sdev_node_t *)ctx;
ASSERT(RW_WRITE_HELD(&sdvp->sdev_contents));
- if (mode != S_IFCHR && mode != S_IFBLK)
+ if (devmode != S_IFCHR && devmode != S_IFBLK)
return (EINVAL);
+ /* Default to relatively safe permission bits if none specified. */
+ if ((mode & 0666) == 0)
+ mode = devmode | 0600;
+
ASSERT(sdvp->sdev_private != NULL);
- vap = *sdev_getdefault_attr(mode == S_IFCHR ? VCHR : VBLK);
+ vap = *sdev_getdefault_attr(devmode == S_IFCHR ? VCHR : VBLK);
gethrestime(&now);
vap.va_atime = now;
vap.va_mtime = now;
vap.va_ctime = now;
vap.va_rdev = dev;
- vap.va_mode = mode | 0666;
+ vap.va_mode = mode;
/* Despite the similar name, this is in fact a different function */
return (sdev_plugin_mknode(sdvp->sdev_private, sdvp, name, &vap));
diff --git a/usr/src/uts/common/io/vnd/vnd.c b/usr/src/uts/common/io/vnd/vnd.c
index 27fdba6..1bd1743 100644
--- a/usr/src/uts/common/io/vnd/vnd.c
+++ b/usr/src/uts/common/io/vnd/vnd.c
@@ -5418,8 +5418,9 @@ vnd_sdev_fillzone(vnd_pnsd_t *nsp, sdev_ctx_t ctx)
mutex_enter(&vdp->vdd_lock);
if ((vdp->vdd_flags & VND_D_LINKED) &&
!(vdp->vdd_flags & (VND_D_CONDEMNED | VND_D_ZONE_DYING))) {
- ret = sdev_plugin_mknod(ctx, vdp->vdd_lname, S_IFCHR,
- vdp->vdd_devid);
+ /* XXX-mg 0666 added for compatibility. Dubious. */
+ ret = sdev_plugin_mknod(ctx, vdp->vdd_lname,
+ S_IFCHR | 0666, vdp->vdd_devid);
if (ret != 0 && ret != EEXIST) {
mutex_exit(&vdp->vdd_lock);
mutex_exit(&nsp->vpnd_lock);
@@ -5463,7 +5464,8 @@ vnd_sdev_filldir_root(sdev_ctx_t ctx)
* Always add a reference to the control node. There's no need to
* reference it since it always exists and is always what we clone from.
*/
- ret = sdev_plugin_mknod(ctx, "ctl", S_IFCHR,
+ /* XXX-mg 0666 added for compatibility. Dubious. */
+ ret = sdev_plugin_mknod(ctx, "ctl", S_IFCHR | 0666,
makedevice(ddi_driver_major(vnd_dip), 0));
if (ret != 0 && ret != EEXIST)
return (ret);
commit 97c495beb6e4dc7330046e5f8198a98b638d7d4e
Author: Mike Gerdts <mike.gerdts@joyent.com>
Date: Sat Dec 30 00:11:14 2017 +0000
OS-XXXX sdev_plugin needs a gitminor function
diff --git a/usr/src/uts/common/fs/dev/sdev_plugin.c b/usr/src/uts/common/fs/dev/sdev_plugin.c
index 8851911..dd81a52 100644
--- a/usr/src/uts/common/fs/dev/sdev_plugin.c
+++ b/usr/src/uts/common/fs/dev/sdev_plugin.c
@@ -145,6 +145,21 @@ sdev_ctx_name(sdev_ctx_t ctx)
return (sdp->sdev_name);
}
+int
+sdev_ctx_minor(sdev_ctx_t ctx, minor_t *minorp)
+{
+ sdev_node_t *sdp = (sdev_node_t *)ctx;
+
+ ASSERT(RW_LOCK_HELD(&sdp->sdev_contents));
+ if (sdp->sdev_vnode->v_type == VCHR ||
+ sdp->sdev_vnode->v_type == VBLK) {
+ *minorp = sdp->sdev_vnode->v_rdev;
+ return (0);
+ }
+
+ return (ENODEV);
+}
+
/*
* Currently we only support psasing through a single flag -- SDEV_IS_GLOBAL.
*/
@@ -159,7 +174,8 @@ sdev_ctx_flags(sdev_ctx_t ctx)
/*
* Return some amount of private data specific to the vtype. In the case of a
- * character or block device this is the device number.
+ * character or block device this is the device number. So as to not confuse
+ * NULL and minor 0, a better interface for minor numbers is sdev_ctx_minor().
*/
const void *
sdev_ctx_vtype_data(sdev_ctx_t ctx)
diff --git a/usr/src/uts/common/sys/fs/sdev_plugin.h b/usr/src/uts/common/sys/fs/sdev_plugin.h
index 8783df5..bfa4ce7 100644
--- a/usr/src/uts/common/sys/fs/sdev_plugin.h
+++ b/usr/src/uts/common/sys/fs/sdev_plugin.h
@@ -88,6 +88,7 @@ typedef enum sdev_ctx_flags {
extern sdev_ctx_flags_t sdev_ctx_flags(sdev_ctx_t);
extern const char *sdev_ctx_name(sdev_ctx_t);
extern const char *sdev_ctx_path(sdev_ctx_t);
+extern int sdev_ctx_minor(sdev_ctx_t, minor_t *);
extern enum vtype sdev_ctx_vtype(sdev_ctx_t);
extern const void *sdev_ctx_vtype_data(sdev_ctx_t);
SDEV_PLUGINS(9F) Kernel Functions for Drivers SDEV_PLUGINS(9F)
NAME
sdev_plugins - plugin interfaces for dev(7FS)
SYNOPSIS
#include <sys/fs/sdev_plugin.h>
sdev_plugin_hdl_t
sdev_plugin_register(const char *name, sdev_plugin_ops_t *sdev_ops,
int *errp);
void
sdev_plugin_unregister(sdev_plugin_hdl_t sdev_hdl);
sdev_ctx_flags_t
sdev_ctx_flags(sdev_ctx_t sdev_ctx);
const char *
sdev_ctx_name(sdev_ctx_t sdev_ctx);
const char *
sdev_ctx_path(sdev_ctx_t sdev_ctx);
int
sdev_ctx_minor(sdev_ctx_t sdev_ctx, minor_t *minorp);
vtype_t
sdev_ctx_vtype(sdev_ctx_t sdev_ctx);
void *
sdev_ctx_vtype_data(sdev_ctx_t sdev_ctx);
int
sdev_plugin_mkdir(sdev_ctx_t sdev_ctx, const char *dirname);
int
sdev_plugin_mknod(sdev_ctx_t sdev_ctx, const char *devname, mode_t mode,
dev_t dev);
INTERFACE LEVEL
Evolving - This interface is still evolving in illumos. API and ABI
stability is not guaranteed.
PARAMETERS
sdev_hdl A sdev_plugin_hdl_t handle, as described in the Plugin
Registration section.
sdev_ops Pointer to sdev_plugin_ops_t structure, as described in the
Plugin Registration section.
sdev_ctx An opaque context passed to the plugin by dev(7FS) to the
various callbacks. See the Context Helper Functions
section for details.
DESCRIPTION
The sdev_plugins interfaces described in this page are used to
dynamically generate directories and device nodes within the /dev
directory. They obviate the need for devfsadm(1M) plugins for modules
that use these interfaces.
Plugin registration
The sdev_plugin_register() function is used to register initial path and
the callbacks used by dev(7FS) as /dev is traversed. The
sdev_plugin_ops_t type is defined as:
typedef struct sdev_plugin_ops {
int spo_version;
sdev_plugin_flags_t spo_flags;
sp_valid_f spo_validate;
sp_filldir_f spo_filldir;
sp_inactive_f spo_inactive;
} sdev_plugin_ops_t;
The value of spo_version should be set to SDEV_PLUGIN_VERSION and
spo_flags may include the following:
SDEV_PLUGIN_NO_NCACHE
XXX FIXME
SDEV_PLUGIN_SUBDIR
This plugin will create devices in a subdirectory of
/dev with a name matching that of the name argument.
See the Callbacks section for details on the spo_validate, spo_filldir,
and spo_inactive callbacks.
The structure referenced by the sdev_ops variable may be used by dev(7FS)
until sdev_plugin_unregister() is called with the same sdev_plugin_hdl_t
as was returned by the earlier call to the sdev_plugin_register()
function.
Callbacks
dev(7FS) will call the callback functions defined in the
sdev_plugin_ops_t as the system accesses relevant paths through the /dev
directory.
Callbacks make extensive use of Context Helper Functions. Additionally,
they will call into dev(7FS) to create subidrectories and device nodes
with the following functions.
int sdev_plugin_mkdir(sdev_ctx_t ctx, const char *dirname)
Creates a subdirectory named dirname within the directory
referenced by ctx.
int sdev_plugin_mknod(sdev_ctx_t ctx, const char *nodename, mode_t mode,
dev_t dev)
Creates a block or character device named nodename within the
directory referenced by ctx. The mode argument must contain
S_IFCHR or S_IFBLK. If no other read or write mode bits are set,
S_IREAD|S_IWRITE (0600) is assumed. See stat.h(3HEAD). The dev
argument is as returned by makedev(3C).
The following callbacks must be implemented by every plugin.
sdev_plugin_validate_t spo_validate(sdev_ctxt_t ctx)
The validate callback is called to verify that a particular device
node or directory is still valid. The callback shall return one of
the following values:
SDEV_VTOR_INVALID
The directory or device node is no longer valid and
should be removed.
SDEV_VTOR_SKIP
XXX
SDEV_VTOR_VALID
The directory or device node is valid and should not
be changed.
SDEV_VTOR_STALE
The directory or device node should be present, but
it is stale and should be regenerated. XXX This
triggers spo_filldir?
int spo_filldir(sdev_ctxt_t ctx)
The fill directory callback is called to generate or re-generate
the contents of a directory. This callback will typically make one
more calls to the spo_plugin_mkdir() and/or spo_plugin_mknod()
functions to create directories and device nodes. This callback
should be tolerant of being called on a directory that is already
partially filled. That is, spo_plugin_mkdir() and
spo_plugin_mknod() may return EEXIST which is likely not a fatal
error.
The callback shall return 0 on success or a valid errno value on
falure.
void spo_inactive(sdev_ctxt_t ctx)
The inactive callback is called when dev(7FS) is removing an entry.
This callback should be used by the module to reduce reference
counts and/or any other house keeping that is required as device
nodes are removed.
If the device(s) are different between the global zone and non-global
zones, callbacks should use sdev_ctx_flags() to check for the SDEV_GLOBAL
flag.
If a module creates a directory hierarchy, sdev_ctx_path() will be
essential to ensuring that operations are being performed in the intended
directory.
Context Helper Functions
Context helper functions are used within callbacks to gain access to
various fields within sdev_ctxt_t structures. See the Callbacks section.
The sdev_ctx_flags() function may retrieve the flags for a particular
directory or device node. The supported flags are:
SDEV_GLOBAL This dev(7FS) instance is in the global zone.
The sdev_ctx_name() function returns the last component of the path of
the directory or device node.
The sdev_ctx_path() function returns the absolute path of the directory
or device node.
The sdev_ctx_minor() function returns via the location referenced by
minorp the minor node of the device node referenced by the sdev_ctx
function argument. If sdev_ctx does not refer to a block or character
device, an error is returned and the location referend by minorp is not
changed.
The sdev_ctx_vtype() function returns the vnode type of the vnode
corresponding to element referenced by the sdev_ctx function argument.
The following values are expected:
VDIR Directory
VBLK Block device
VCHR Character device
The dev_ctx_vtype_data() function is obsolete. Use dev_ctx_minor()
instead.
CONTEXT
These functions may be called only in kernel context.
RETURN VALUES
The sdev_plugin_register() function returns a non-NULL value on success.
On failure it returns NULL and if errp is non-NULL, errp is set to an
appropriate errno value. If sdev_ops is not properly initialized, this
value will be EINVAL. If the plugin is already registered or there is
another name collision, EEXIST is returned via errp.
SEE ALSO
devfsadm(1M), makedev(3C), stat.h(3HEAD), dev(7FS)
illumos December 30, 2017 illumos
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment