[ndctl,2/2] libdaxctl: fix device reconfiguration with builtin drivers
diff mbox series

Message ID 20190904010819.11012-2-vishal.l.verma@intel.com
State New
Headers show
Series
  • [ndctl,1/2] libdaxctl: fix the system-ram capability check
Related show

Commit Message

Verma, Vishal L Sept. 4, 2019, 1:08 a.m. UTC
When the driver of a given reconfiguration mode is builtin, libdaxctl
isn't able to build a module lookup list using kmod. However, it doesn't
need to fail in this case, as it is acceptable for a driver to be
builtin.

Use the kmod 'initstate' to determine whether the target driver may be
builtin, and ensure it is available by probing it via a named lookup.
If it is available, skip the modalias based list walk, and bind to it
directly.

Link: https://github.com/pmem/ndctl/issues/108
Cc: Dan Williams <dan.j.williams@intel.com>
Reported-by: Brice Goglin <Brice.Goglin@inria.fr>
Reported-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
---
 daxctl/lib/libdaxctl.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

Comments

Dan Williams Sept. 4, 2019, 2:20 a.m. UTC | #1
On Tue, Sep 3, 2019 at 6:08 PM Vishal Verma <vishal.l.verma@intel.com> wrote:
>
> When the driver of a given reconfiguration mode is builtin, libdaxctl
> isn't able to build a module lookup list using kmod. However, it doesn't
> need to fail in this case, as it is acceptable for a driver to be
> builtin.
>
> Use the kmod 'initstate' to determine whether the target driver may be
> builtin, and ensure it is available by probing it via a named lookup.
> If it is available, skip the modalias based list walk, and bind to it
> directly.
>
> Link: https://github.com/pmem/ndctl/issues/108
> Cc: Dan Williams <dan.j.williams@intel.com>
> Reported-by: Brice Goglin <Brice.Goglin@inria.fr>
> Reported-by: Dave Hansen <dave.hansen@linux.intel.com>
> Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
> ---
>  daxctl/lib/libdaxctl.c | 33 +++++++++++++++++++++++++++++++++
>  1 file changed, 33 insertions(+)
>
> diff --git a/daxctl/lib/libdaxctl.c b/daxctl/lib/libdaxctl.c
> index d9f2c33..7a65bed 100644
> --- a/daxctl/lib/libdaxctl.c
> +++ b/daxctl/lib/libdaxctl.c
> @@ -868,6 +868,37 @@ DAXCTL_EXPORT int daxctl_dev_is_enabled(struct daxctl_dev *dev)
>         return is_enabled(path);
>  }
>
> +static int try_kmod_builtin(struct daxctl_dev *dev, const char *mod_name)
> +{
> +       const char *devname = daxctl_dev_get_devname(dev);
> +       struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
> +       struct kmod_module *kmod;
> +       int rc = -ENXIO;
> +
> +       rc = kmod_module_new_from_name(ctx->kmod_ctx, mod_name, &kmod);
> +       if (rc < 0) {
> +               err(ctx, "%s: failed getting module for: %s: %s\n",
> +                       devname, mod_name, strerror(-rc));
> +               return rc;
> +       }
> +
> +       if (kmod_module_get_initstate(kmod) != KMOD_MODULE_BUILTIN)
> +               return -ENXIO;
> +
> +       dbg(ctx, "%s inserting module: %s\n", devname,
> +               kmod_module_get_name(kmod));
> +       rc = kmod_module_probe_insert_module(kmod,
> +                       KMOD_PROBE_APPLY_BLACKLIST,
> +                       NULL, NULL, NULL, NULL);
> +       if (rc < 0) {
> +               err(ctx, "%s: insert failure: %d\n", devname, rc);
> +               return rc;
> +       }
> +       dev->module = kmod;
> +
> +       return 0;
> +}
> +
>  static int daxctl_insert_kmod_for_mode(struct daxctl_dev *dev,
>                 const char *mod_name)
>  {
> @@ -877,6 +908,8 @@ static int daxctl_insert_kmod_for_mode(struct daxctl_dev *dev,
>         int rc = -ENXIO;
>
>         if (dev->kmod_list == NULL) {

Hmm, why wait until now to check if this list is NULL. How about fall
back to kmod_module_new_from_name() at to_module_list() time? That
would seem to simplify this follow up routine to not need to worry
about working around a NULL list.
Brice Goglin Sept. 4, 2019, 5:30 p.m. UTC | #2
Thanks, this works here (on a Debian testing with vanilla 5.2.11 and
5.3-rc7).

Brice


Le 04/09/2019 à 03:08, Vishal Verma a écrit :
> When the driver of a given reconfiguration mode is builtin, libdaxctl
> isn't able to build a module lookup list using kmod. However, it doesn't
> need to fail in this case, as it is acceptable for a driver to be
> builtin.
>
> Use the kmod 'initstate' to determine whether the target driver may be
> builtin, and ensure it is available by probing it via a named lookup.
> If it is available, skip the modalias based list walk, and bind to it
> directly.
>
> Link: https://github.com/pmem/ndctl/issues/108
> Cc: Dan Williams <dan.j.williams@intel.com>
> Reported-by: Brice Goglin <Brice.Goglin@inria.fr>
> Reported-by: Dave Hansen <dave.hansen@linux.intel.com>
> Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
> ---
>  daxctl/lib/libdaxctl.c | 33 +++++++++++++++++++++++++++++++++
>  1 file changed, 33 insertions(+)
>
> diff --git a/daxctl/lib/libdaxctl.c b/daxctl/lib/libdaxctl.c
> index d9f2c33..7a65bed 100644
> --- a/daxctl/lib/libdaxctl.c
> +++ b/daxctl/lib/libdaxctl.c
> @@ -868,6 +868,37 @@ DAXCTL_EXPORT int daxctl_dev_is_enabled(struct daxctl_dev *dev)
>  	return is_enabled(path);
>  }
>  
> +static int try_kmod_builtin(struct daxctl_dev *dev, const char *mod_name)
> +{
> +	const char *devname = daxctl_dev_get_devname(dev);
> +	struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
> +	struct kmod_module *kmod;
> +	int rc = -ENXIO;
> +
> +	rc = kmod_module_new_from_name(ctx->kmod_ctx, mod_name, &kmod);
> +	if (rc < 0) {
> +		err(ctx, "%s: failed getting module for: %s: %s\n",
> +			devname, mod_name, strerror(-rc));
> +		return rc;
> +	}
> +
> +	if (kmod_module_get_initstate(kmod) != KMOD_MODULE_BUILTIN)
> +		return -ENXIO;
> +
> +	dbg(ctx, "%s inserting module: %s\n", devname,
> +		kmod_module_get_name(kmod));
> +	rc = kmod_module_probe_insert_module(kmod,
> +			KMOD_PROBE_APPLY_BLACKLIST,
> +			NULL, NULL, NULL, NULL);
> +	if (rc < 0) {
> +		err(ctx, "%s: insert failure: %d\n", devname, rc);
> +		return rc;
> +	}
> +	dev->module = kmod;
> +
> +	return 0;
> +}
> +
>  static int daxctl_insert_kmod_for_mode(struct daxctl_dev *dev,
>  		const char *mod_name)
>  {
> @@ -877,6 +908,8 @@ static int daxctl_insert_kmod_for_mode(struct daxctl_dev *dev,
>  	int rc = -ENXIO;
>  
>  	if (dev->kmod_list == NULL) {
> +		if (try_kmod_builtin(dev, mod_name) == 0)
> +			return 0;
>  		err(ctx, "%s: a modalias lookup list was not created\n",
>  				devname);
>  		return rc;
Verma, Vishal L Sept. 4, 2019, 8:27 p.m. UTC | #3
On Tue, 2019-09-03 at 19:20 -0700, Dan Williams wrote:
> 
> > +static int try_kmod_builtin(struct daxctl_dev *dev, const char *mod_name)
> > +{
> > +       const char *devname = daxctl_dev_get_devname(dev);
> > +       struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
> > +       struct kmod_module *kmod;
> > +       int rc = -ENXIO;
> > +
> > +       rc = kmod_module_new_from_name(ctx->kmod_ctx, mod_name, &kmod);
> > +       if (rc < 0) {
> > +               err(ctx, "%s: failed getting module for: %s: %s\n",
> > +                       devname, mod_name, strerror(-rc));
> > +               return rc;
> > +       }
> > +
> > +       if (kmod_module_get_initstate(kmod) != KMOD_MODULE_BUILTIN)
> > +               return -ENXIO;
> > +
> > +       dbg(ctx, "%s inserting module: %s\n", devname,
> > +               kmod_module_get_name(kmod));
> > +       rc = kmod_module_probe_insert_module(kmod,
> > +                       KMOD_PROBE_APPLY_BLACKLIST,
> > +                       NULL, NULL, NULL, NULL);
> > +       if (rc < 0) {
> > +               err(ctx, "%s: insert failure: %d\n", devname, rc);
> > +               return rc;
> > +       }
> > +       dev->module = kmod;
> > +
> > +       return 0;
> > +}
> > +
> >  static int daxctl_insert_kmod_for_mode(struct daxctl_dev *dev,
> >                 const char *mod_name)
> >  {
> > @@ -877,6 +908,8 @@ static int daxctl_insert_kmod_for_mode(struct daxctl_dev *dev,
> >         int rc = -ENXIO;
> > 
> >         if (dev->kmod_list == NULL) {
> 
> Hmm, why wait until now to check if this list is NULL. How about fall
> back to kmod_module_new_from_name() at to_module_list() time? That
> would seem to simplify this follow up routine to not need to worry
> about working around a NULL list.

So we moved the list checking to later in the process around v4 of the
original series, so that we don't unnecessarily fail add_dax_dev() if
for some reason a list wasn't created.

Also, we use mod_name = dax_modules[mode] during an 'enable' to
determine the module name to use for the fallback - we wouldn't have
this at add_dax_dev() time.
Dan Williams Sept. 4, 2019, 9:01 p.m. UTC | #4
On Wed, Sep 4, 2019 at 1:27 PM Verma, Vishal L <vishal.l.verma@intel.com> wrote:
>
> On Tue, 2019-09-03 at 19:20 -0700, Dan Williams wrote:
> >
> > > +static int try_kmod_builtin(struct daxctl_dev *dev, const char *mod_name)
> > > +{
> > > +       const char *devname = daxctl_dev_get_devname(dev);
> > > +       struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
> > > +       struct kmod_module *kmod;
> > > +       int rc = -ENXIO;
> > > +
> > > +       rc = kmod_module_new_from_name(ctx->kmod_ctx, mod_name, &kmod);
> > > +       if (rc < 0) {
> > > +               err(ctx, "%s: failed getting module for: %s: %s\n",
> > > +                       devname, mod_name, strerror(-rc));
> > > +               return rc;
> > > +       }
> > > +
> > > +       if (kmod_module_get_initstate(kmod) != KMOD_MODULE_BUILTIN)
> > > +               return -ENXIO;
> > > +
> > > +       dbg(ctx, "%s inserting module: %s\n", devname,
> > > +               kmod_module_get_name(kmod));
> > > +       rc = kmod_module_probe_insert_module(kmod,
> > > +                       KMOD_PROBE_APPLY_BLACKLIST,
> > > +                       NULL, NULL, NULL, NULL);
> > > +       if (rc < 0) {
> > > +               err(ctx, "%s: insert failure: %d\n", devname, rc);
> > > +               return rc;
> > > +       }
> > > +       dev->module = kmod;
> > > +
> > > +       return 0;
> > > +}
> > > +
> > >  static int daxctl_insert_kmod_for_mode(struct daxctl_dev *dev,
> > >                 const char *mod_name)
> > >  {
> > > @@ -877,6 +908,8 @@ static int daxctl_insert_kmod_for_mode(struct daxctl_dev *dev,
> > >         int rc = -ENXIO;
> > >
> > >         if (dev->kmod_list == NULL) {
> >
> > Hmm, why wait until now to check if this list is NULL. How about fall
> > back to kmod_module_new_from_name() at to_module_list() time? That
> > would seem to simplify this follow up routine to not need to worry
> > about working around a NULL list.
>
> So we moved the list checking to later in the process around v4 of the
> original series, so that we don't unnecessarily fail add_dax_dev() if
> for some reason a list wasn't created.

Ah true, I forgot that wrinkle, however...

> Also, we use mod_name = dax_modules[mode] during an 'enable' to
> determine the module name to use for the fallback - we wouldn't have
> this at add_dax_dev() time.

Since modalias is already not reliable it seems the implementation
should go ahead never do module lookups and just do everything based
on module names.

In other words the libndctl panacea of not needing to hard code module
names is already lost in libdaxctl land. If the code drops modalias
usage does that clean up some of these flows?
Verma, Vishal L Sept. 4, 2019, 9:17 p.m. UTC | #5
On Wed, 2019-09-04 at 14:01 -0700, Dan Williams wrote:
> On Wed, Sep 4, 2019 at 1:27 PM Verma, Vishal L <vishal.l.verma@intel.com> wrote:
> > On Tue, 2019-09-03 at 19:20 -0700, Dan Williams wrote:
> > > 
> > > Hmm, why wait until now to check if this list is NULL. How about fall
> > > back to kmod_module_new_from_name() at to_module_list() time? That
> > > would seem to simplify this follow up routine to not need to worry
> > > about working around a NULL list.
> > 
> > So we moved the list checking to later in the process around v4 of the
> > original series, so that we don't unnecessarily fail add_dax_dev() if
> > for some reason a list wasn't created.
> 
> Ah true, I forgot that wrinkle, however...
> 
> > Also, we use mod_name = dax_modules[mode] during an 'enable' to
> > determine the module name to use for the fallback - we wouldn't have
> > this at add_dax_dev() time.
> 
> Since modalias is already not reliable it seems the implementation
> should go ahead never do module lookups and just do everything based
> on module names.
> 
> In other words the libndctl panacea of not needing to hard code module
> names is already lost in libdaxctl land. If the code drops modalias
> usage does that clean up some of these flows?

Yep I think so - we use modalias to construct a lookup list, but we
still have to use the name to resolve to the final module based on the
mode. I think we can remove the list lookup and replace it with simply:

	kmod_module_new_from_name(ctx->kmod_ctx, mod_name, &kmod);

It would clean up the module related flows, but is there any
disadvantage to doing this?
Dan Williams Sept. 4, 2019, 9:39 p.m. UTC | #6
On Wed, Sep 4, 2019 at 2:17 PM Verma, Vishal L <vishal.l.verma@intel.com> wrote:
>
> On Wed, 2019-09-04 at 14:01 -0700, Dan Williams wrote:
> > On Wed, Sep 4, 2019 at 1:27 PM Verma, Vishal L <vishal.l.verma@intel.com> wrote:
> > > On Tue, 2019-09-03 at 19:20 -0700, Dan Williams wrote:
> > > >
> > > > Hmm, why wait until now to check if this list is NULL. How about fall
> > > > back to kmod_module_new_from_name() at to_module_list() time? That
> > > > would seem to simplify this follow up routine to not need to worry
> > > > about working around a NULL list.
> > >
> > > So we moved the list checking to later in the process around v4 of the
> > > original series, so that we don't unnecessarily fail add_dax_dev() if
> > > for some reason a list wasn't created.
> >
> > Ah true, I forgot that wrinkle, however...
> >
> > > Also, we use mod_name = dax_modules[mode] during an 'enable' to
> > > determine the module name to use for the fallback - we wouldn't have
> > > this at add_dax_dev() time.
> >
> > Since modalias is already not reliable it seems the implementation
> > should go ahead never do module lookups and just do everything based
> > on module names.
> >
> > In other words the libndctl panacea of not needing to hard code module
> > names is already lost in libdaxctl land. If the code drops modalias
> > usage does that clean up some of these flows?
>
> Yep I think so - we use modalias to construct a lookup list, but we
> still have to use the name to resolve to the final module based on the
> mode. I think we can remove the list lookup and replace it with simply:
>
>         kmod_module_new_from_name(ctx->kmod_ctx, mod_name, &kmod);
>
> It would clean up the module related flows, but is there any
> disadvantage to doing this?

The small disadvantage is that now libdaxctl is not immune to upstream
kernel reworks that might rename, or eliminate the module. libndctl
has that immunity to those type of reworks, but it is only a
theoretical problem. In practice modules don't renamed or eliminated
all that often. In the case of dax the device-model reworks almost
violated that assumption, but CONFIG_DEV_DAX_PMEM_COMPAT covered the
gap.

Patch
diff mbox series

diff --git a/daxctl/lib/libdaxctl.c b/daxctl/lib/libdaxctl.c
index d9f2c33..7a65bed 100644
--- a/daxctl/lib/libdaxctl.c
+++ b/daxctl/lib/libdaxctl.c
@@ -868,6 +868,37 @@  DAXCTL_EXPORT int daxctl_dev_is_enabled(struct daxctl_dev *dev)
 	return is_enabled(path);
 }
 
+static int try_kmod_builtin(struct daxctl_dev *dev, const char *mod_name)
+{
+	const char *devname = daxctl_dev_get_devname(dev);
+	struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
+	struct kmod_module *kmod;
+	int rc = -ENXIO;
+
+	rc = kmod_module_new_from_name(ctx->kmod_ctx, mod_name, &kmod);
+	if (rc < 0) {
+		err(ctx, "%s: failed getting module for: %s: %s\n",
+			devname, mod_name, strerror(-rc));
+		return rc;
+	}
+
+	if (kmod_module_get_initstate(kmod) != KMOD_MODULE_BUILTIN)
+		return -ENXIO;
+
+	dbg(ctx, "%s inserting module: %s\n", devname,
+		kmod_module_get_name(kmod));
+	rc = kmod_module_probe_insert_module(kmod,
+			KMOD_PROBE_APPLY_BLACKLIST,
+			NULL, NULL, NULL, NULL);
+	if (rc < 0) {
+		err(ctx, "%s: insert failure: %d\n", devname, rc);
+		return rc;
+	}
+	dev->module = kmod;
+
+	return 0;
+}
+
 static int daxctl_insert_kmod_for_mode(struct daxctl_dev *dev,
 		const char *mod_name)
 {
@@ -877,6 +908,8 @@  static int daxctl_insert_kmod_for_mode(struct daxctl_dev *dev,
 	int rc = -ENXIO;
 
 	if (dev->kmod_list == NULL) {
+		if (try_kmod_builtin(dev, mod_name) == 0)
+			return 0;
 		err(ctx, "%s: a modalias lookup list was not created\n",
 				devname);
 		return rc;