[libvirt] Weekly meeting minutes May 22nd, 2014
by Daniel P. Berrange
Agenda + minutes from 22/05/2014
* Welcome / rollcall
* IRC comments from:
* eblake
* danpb
* pkrempa
* derRichard
* rbogorodskiy
* mkletzan
* nehaljwani
* mprivozn
* Next release schedule
* Freeze: Mon May 26th
* Release: Mon June 2nd
* Patches needing review
* pkrempa's gluster patches
* 1-27 are nice to have but not release critical
* 28+ need to wait for QEMU work
* eblake's live commit work
* minimum need patch to avoid hang with qemu 2.0
* remaining patches should rebase on top of pkrempa, even if it
misses release
* vbox snapshot patches - been waiting a long time
* Jim Fehlig has libxl migration patches - probably desired for the
release
* Roman has bhyve pci allocation patches
* Refactoring of PCI stuff already merged, just bhyve specific
bits left
* Nehal has lease helper patch pending
* eblake to update to latest gnulib pre-freeze, unless the gnulib
change from STREQ macro to inline function streq() requires lots
of fallout
* Michael has "Keep original file label" left over from March, not
release critical though
* Richard W suggests to add support for capabilties for LXC
* Allows apps to be started with less caps (ie drop CAP_NET_ADMIN to
prevent IP changes)
* Could also allow uid/gid to be set
Thanks to all for attending this first meeting. Set to repeat again
on May 29th @ 1400 UTC in #virt-meeting on irc.oftc.net
Regards,
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
10 years, 6 months
[libvirt] [PATCH 0/2] qemu: Fix few snapshot issues
by Peter Krempa
Peter Krempa (2):
qemu: snapshot: Reject internal active snapshot without memory state
qemu: snapshot: Improve detection of mixed snapshots
src/qemu/qemu_driver.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
--
1.9.3
10 years, 6 months
[libvirt] [PATCH] util: storage: Fix crash of libvirtd on network backed guest block-pull
by Peter Krempa
For guests backed by gluster volumes (or other network storage) we don't
fill the backing chain (see qemuDomainDetermineDiskChain). This leaves
the "relPath" field of the top image NULL. This causes a crash in
virStorageFileChainLookup() when looking up a backing element for such a
disk.
Since I'm working on adding support for network storage and one of the
steps will make the "relPath" field optional let's use STREQ_NULLABLE
instead of STREQ in virStorageFileChainLookup() to avoid the problem.
---
src/util/virstoragefile.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
index 2feda67..c9b6187 100644
--- a/src/util/virstoragefile.c
+++ b/src/util/virstoragefile.c
@@ -1591,7 +1591,7 @@ virStorageFileChainLookup(virStorageSourcePtr chain,
if (idx == i)
break;
} else {
- if (STREQ(name, chain->relPath))
+ if (STREQ_NULLABLE(name, chain->relPath))
break;
if (nameIsFile && (chain->type == VIR_STORAGE_TYPE_FILE ||
chain->type == VIR_STORAGE_TYPE_BLOCK)) {
--
1.9.3
10 years, 6 months
[libvirt] [PATCH V2] virsh: forbid negative vcpu argument to vcpupin.
by Jincheng Miao
vcpupin will allow argument --vcpu as a signed number,
and pass it to virDomainPinVcpu directlly without
checking if this value is positive(valid).
> virsh vcpupin r7 -1 0
error: numerical overflow: input too large: 4294967295
This message is inaccurate, and the negative vcpu is
non-valuable. So forbid vcpu argument as a negative.
After patching, the result likes:
> virsh vcpupin r6 -1
error: vcpupin: Invalid vCPU number.
> virsh vcpupin r6 --cpulist 0-1
error: vcpupin: Missing vCPU number in pin mode.
> virsh vcpupin r6 --vcpu ABC
error: vcpupin: Invalid vCPU number in query mode.
Signed-off-by: Jincheng Miao <jmiao(a)redhat.com>
---
tools/virsh-domain.c | 42 ++++++++++++++++++++++++------------------
1 files changed, 24 insertions(+), 18 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 84a6706..e302459 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -5797,7 +5797,7 @@ cmdVcpuPin(vshControl *ctl, const vshCmd *cmd)
{
virDomainInfo info;
virDomainPtr dom;
- int vcpu = -1;
+ unsigned int vcpu;
const char *cpulist = NULL;
bool ret = false;
unsigned char *cpumap = NULL;
@@ -5809,6 +5809,7 @@ cmdVcpuPin(vshControl *ctl, const vshCmd *cmd)
bool live = vshCommandOptBool(cmd, "live");
bool current = vshCommandOptBool(cmd, "current");
bool query = false; /* Query mode if no cpulist */
+ int get_vcpu;
unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
VSH_EXCLUSIVE_OPTIONS_VAR(current, live);
@@ -5830,29 +5831,34 @@ cmdVcpuPin(vshControl *ctl, const vshCmd *cmd)
query = !cpulist;
- /* In query mode, "vcpu" is optional */
- if (vshCommandOptInt(cmd, "vcpu", &vcpu) < !query) {
- vshError(ctl, "%s",
- _("vcpupin: Invalid or missing vCPU number."));
- virDomainFree(dom);
- return false;
- }
-
- if ((maxcpu = vshNodeGetCPUCount(ctl->conn)) < 0) {
- virDomainFree(dom);
- return false;
+ get_vcpu = vshCommandOptUInt(cmd, "vcpu", &vcpu);
+ if (get_vcpu <= 0) {
+ /* In query mode, "vcpu" is optional */
+ if (query && get_vcpu < 0) {
+ vshError(ctl, "%s",
+ _("vcpupin: Invalid vCPU number in query mode."));
+ goto cleanup;
+ }
+ /* In pin mode, "vcpu" is necessary */
+ if (!query) {
+ vshError(ctl, "%s",
+ _("vcpupin: Missing vCPU number in pin mode."));
+ goto cleanup;
+ }
}
if (virDomainGetInfo(dom, &info) != 0) {
vshError(ctl, "%s", _("vcpupin: failed to get domain information."));
- virDomainFree(dom);
- return false;
+ goto cleanup;
}
if (vcpu >= info.nrVirtCpu) {
vshError(ctl, "%s", _("vcpupin: Invalid vCPU number."));
- virDomainFree(dom);
- return false;
+ goto cleanup;
+ }
+
+ if ((maxcpu = vshNodeGetCPUCount(ctl->conn)) < 0) {
+ goto cleanup;
}
cpumaplen = VIR_CPU_MAPLEN(maxcpu);
@@ -5871,7 +5877,7 @@ cmdVcpuPin(vshControl *ctl, const vshCmd *cmd)
vshPrintExtra(ctl, "%s %s\n", _("VCPU:"), _("CPU Affinity"));
vshPrintExtra(ctl, "----------------------------------\n");
for (i = 0; i < ncpus; i++) {
- if (vcpu != -1 && i != vcpu)
+ if (get_vcpu > 0 && i != vcpu)
continue;
vshPrint(ctl, "%4zu: ", i);
@@ -5880,8 +5886,8 @@ cmdVcpuPin(vshControl *ctl, const vshCmd *cmd)
if (!ret)
break;
}
-
}
+
VIR_FREE(cpumaps);
goto cleanup;
}
--
1.7.1
10 years, 6 months
[libvirt] [PATCHv2] util: fix virTimeLocalOffsetFromUTC DST processing
by Laine Stump
The original version of virTimeLocalOffsetFromUTC() would fail for
certain times of the day if daylight savings time was active. This
could most easily be seen by uncommenting the TEST_LOCALOFFSET() cases
that include a DST setting.
After a lot of experimenting, I found that the way to solve it in
almost all test cases is to set tm_isdst = -1 in the stuct tm prior to
calling mktime(). Once this is done, the correct offset is returned
for all test cases at all times except the two hours just after
00:00:00 Jan 1 UTC - during that time, any timezone that is *behind*
UTC, and that is supposed to always be in DST will not have DST
accounted for in its offset.
I believe that the code of virTimeLocalOffsetFromUTC() is actually
correct for all cases, but the problem still encountered is due to our
inability to come up with a TZ string that properly forces DST to
*always* be active. Since a modfication of the (currently fixed)
expected result data to account for this would necessarily use the same
functions that we're trying to test, I've instead just made the test
program conditionally bypass the problematic cases if the current date
is either December 31 or January 1. This way we get maximum testing
during 363 days of the year, but don't get false failures on Dec 31
and Jan 1.
---
Change from V1: correct typo in commit message pointed out by Eric,
and also followed his suggestion to enable the sometimes-failing tests
unless the current localtime is Jan 1 or Dec 31.
src/util/virtime.c | 3 +++
tests/virtimetest.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 56 insertions(+), 8 deletions(-)
diff --git a/src/util/virtime.c b/src/util/virtime.c
index 3a56400..c69dff1 100644
--- a/src/util/virtime.c
+++ b/src/util/virtime.c
@@ -377,6 +377,9 @@ virTimeLocalOffsetFromUTC(long *offset)
return -1;
}
+ /* tell mktime to figure out itself whether or not DST is in effect */
+ gmtimeinfo.tm_isdst = -1;
+
/* mktime() also obeys current timezone rules */
if ((utc = mktime(&gmtimeinfo)) == (time_t)-1) {
virReportSystemError(errno, "%s",
diff --git a/tests/virtimetest.c b/tests/virtimetest.c
index bf27682..f378076 100644
--- a/tests/virtimetest.c
+++ b/tests/virtimetest.c
@@ -101,6 +101,28 @@ testTimeLocalOffset(const void *args)
return 0;
}
+
+/* return true if the date is Jan 1 or Dec 31 (localtime) */
+static bool
+IsJan1OrDec31(void)
+{
+ time_t current = time(NULL);
+ struct tm timeinfo;
+
+ if (current == (time_t)-1) {
+ VIR_DEBUG("time() failed");
+ return false;
+ }
+ if (!localtime_r(¤t, &timeinfo)) {
+ VIR_DEBUG("localtime_r() failed");
+ return false;
+ }
+
+ return (timeinfo.tm_mon == 0 && timeinfo.tm_mday == 1) ||
+ (timeinfo.tm_mon == 11 && timeinfo.tm_mday == 31);
+}
+
+
static int
mymain(void)
{
@@ -161,21 +183,44 @@ mymain(void)
TEST_LOCALOFFSET("VIR00:30", -30 * 60);
TEST_LOCALOFFSET("VIR01:30", -90 * 60);
+ TEST_LOCALOFFSET("VIR05:00", (-5 * 60) * 60);
TEST_LOCALOFFSET("UTC", 0);
TEST_LOCALOFFSET("VIR-00:30", 30 * 60);
TEST_LOCALOFFSET("VIR-01:30", 90 * 60);
-#if __TEST_DST
+
/* test DST processing with timezones that always
* have DST in effect; what's more, cover a zone with
* with an unusual DST different than a usual one hour
*/
- /* NB: These tests fail at certain times of the day, so
- * must be disabled until we figure out why
- */
- TEST_LOCALOFFSET("VIR-00:30VID,0,365", 90 * 60);
- TEST_LOCALOFFSET("VIR-02:30VID,0,365", 210 * 60);
- TEST_LOCALOFFSET("VIR-02:30VID-04:30,0,365", 270 * 60);
-#endif
+ TEST_LOCALOFFSET("VIR-00:30VID,0/00:00:00,366/23:59:59",
+ ((1 * 60) + 30) * 60);
+ TEST_LOCALOFFSET("VIR-02:30VID,0/00:00:00,366/23:59:59",
+ ((3 * 60) + 30) * 60);
+ TEST_LOCALOFFSET("VIR-02:30VID-04:30,0/00:00:00,366/23:59:59",
+ ((4 * 60) + 30) * 60);
+ TEST_LOCALOFFSET("VIR-12:00VID-13:00,0/00:00:00,366/23:59:59",
+ ((13 * 60) + 0) * 60);
+
+ if (!IsJan1OrDec31()) {
+ /* experiments have shown that the following tests will fail
+ * during certain hours of Dec 31 or Jan 1 (depending on the
+ * TZ setting in the shell running the test, but in general
+ * for a period that apparently starts at 00:00:00 UTC Jan 1
+ * and continues for 1 - 2 hours). We've determined this is
+ * due to our inability to specify a timezone with DST on/off
+ * settings that make it truly *always* on DST - i.e. it is a
+ * failing of the test data, *not* of the function we are
+ * testing. So to test as much as possible, we still run these
+ * tests, except on Dec 31 and Jan 1.
+ */
+
+ TEST_LOCALOFFSET("VIR02:45VID00:45,0/00:00:00,366/23:59:59",
+ -45 * 60);
+ TEST_LOCALOFFSET("VIR05:00VID04:00,0/00:00:00,366/23:59:59",
+ ((-4 * 60) + 0) * 60);
+ TEST_LOCALOFFSET("VIR11:00VID10:00,0/00:00:00,366/23:59:59",
+ ((-10 * 60) + 0) * 60);
+ }
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
--
1.9.3
10 years, 6 months
[libvirt] [PATCH] Add capability to example AppArmor profile
by Steven Leung
I encountered an AppArmor denial in Ubuntu 14.04. I had filed a bug here https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/1324251
I just wanted to see this applied upstream from Ubuntu. This update to the profile is necessary to write to 9pfs mounts. Let me know what you think about the following patch:
diff --git a/examples/apparmor/libvirt-qemu b/examples/apparmor/libvirt-qemu
index 83814ec..c80294c 100644
--- a/examples/apparmor/libvirt-qemu
+++ b/examples/apparmor/libvirt-qemu
@@ -9,6 +9,10 @@
capability dac_read_search,
capability chown,
+ # to create and modify with 9p shares
+ capability fowner,
+ capability fsetid,
+
# needed to drop privileges
capability setgid,
capability setuid,
I’m running on libvirt: 1.2.2
My host machine is: x86_64
The hypervisor is: KVM
--
Steven
10 years, 6 months
[libvirt] [patch v3 0/2] add support for migrateURI configuration
by Chen Fan
For now, we set the migration URI via command line '--migrate_uri' or
construct the URI by looking up the dest host's hostname which could be
solved by DNS automatically.
But in cases the dest host have two or more NICs to reach, we may need to
send the migration data over a specific NIC which is different from the
automatically resloved one for some reason like performance, security, etc.
thus we must explicitly specify the migrateuri in command line everytime,
but it is too troublesome if there are many such hosts(and don't forget
virt-manager).
This patches add a configuration file option on dest host to save the
default migrate uri which explicitly specify which of this host's
addresses is used for transferring data, thus user doesn't boring
to specify it in command line everytime.
Any comments are welcome.
Thank you very much.
Chen Fan (2):
Add support for migration URI configuration
add inotify handler to qemu driver
src/qemu/qemu.conf | 5 ++-
src/qemu/qemu_conf.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_conf.h | 11 +++++-
src/qemu/qemu_driver.c | 25 ++++++++++++-
src/qemu/qemu_migration.c | 5 +++
5 files changed, 132 insertions(+), 3 deletions(-)
--
1.8.1.4
10 years, 7 months
[libvirt] [PATCH] virsh: fix typos in virsh man page
by Eric Blake
* tools/virsh.pod (attach-disk): Drop duplicate --config, fix typo
in --sourcetype.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
Puhsing under the trivial rule.
tools/virsh.pod | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/virsh.pod b/tools/virsh.pod
index de9a4f7..02671b4 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -2046,7 +2046,7 @@ expected.
=item B<attach-disk> I<domain> I<source> I<target>
[[[I<--live>] [I<--config>] | [I<--current>]] | [I<--persistent>]]
[I<--driver driver>] [I<--subdriver subdriver>] [I<--cache cache>]
-[I<--type type>] [I<--mode mode>] [I<--config>] [I<--sourcetype soucetype>]
+[I<--type type>] [I<--mode mode>] [I<--sourcetype sourcetype>]
[I<--serial serial>] [I<--wwn wwn>] [I<--rawio>]
[I<--address address>] [I<--multifunction>] [I<--print-xml>]
--
1.9.3
10 years, 7 months
[libvirt] [PATCH] maint: cleanup detection of const'ness of selinux ctx
by Jim Fehlig
Commit 292d3f2d fixed the build with libselinux 2.3, but missed
some suggestions by eblake
https://www.redhat.com/archives/libvir-list/2014-May/msg00977.html
This patch changes the macro introduced in 292d3f2d to either be
empty in the case of newer libselinux, or contain 'const' in the
case of older libselinux. The macro is then used directly in
tests/securityselinuxhelper.c.
---
m4/virt-selinux.m4 | 7 +++++--
tests/securityselinuxhelper.c | 24 ++++--------------------
2 files changed, 9 insertions(+), 22 deletions(-)
diff --git a/m4/virt-selinux.m4 b/m4/virt-selinux.m4
index 1d899d5..a6f89ba 100644
--- a/m4/virt-selinux.m4
+++ b/m4/virt-selinux.m4
@@ -39,8 +39,11 @@ int setcon(const security_context_t context);
[gt_cv_setcon_param='security_context_t'],
[gt_cv_setcon_param='const char*'])])
if test "$gt_cv_setcon_param" = 'const char*'; then
- AC_DEFINE_UNQUOTED([SELINUX_CTX_CHAR_PTR], 1,
- [SELinux uses newer char * for security context])
+ AC_DEFINE([VIR_SELINUX_CTX_CONST], [const],
+ [SELinux uses newer const char * for security context])
+ else
+ AC_DEFINE([VIR_SELINUX_CTX_CONST], [],
+ [SELinux uses newer const char * for security context])
fi
AC_MSG_CHECKING([SELinux mount point])
diff --git a/tests/securityselinuxhelper.c b/tests/securityselinuxhelper.c
index af4fae4..1252c15 100644
--- a/tests/securityselinuxhelper.c
+++ b/tests/securityselinuxhelper.c
@@ -156,11 +156,7 @@ int getpidcon(pid_t pid, security_context_t *context)
return getpidcon_raw(pid, context);
}
-#ifdef SELINUX_CTX_CHAR_PTR
-int setcon_raw(const char *context)
-#else
-int setcon_raw(security_context_t context)
-#endif
+int setcon_raw(VIR_SELINUX_CTX_CONST char *context)
{
if (!is_selinux_enabled()) {
errno = EINVAL;
@@ -169,21 +165,13 @@ int setcon_raw(security_context_t context)
return setenv("FAKE_SELINUX_CONTEXT", context, 1);
}
-#ifdef SELINUX_CTX_CHAR_PTR
-int setcon(const char *context)
-#else
-int setcon(security_context_t context)
-#endif
+int setcon(VIR_SELINUX_CTX_CONST char *context)
{
return setcon_raw(context);
}
-#ifdef SELINUX_CTX_CHAR_PTR
-int setfilecon_raw(const char *path, const char *con)
-#else
-int setfilecon_raw(const char *path, security_context_t con)
-#endif
+int setfilecon_raw(const char *path, VIR_SELINUX_CTX_CONST char *con)
{
const char *constr = con;
if (STRPREFIX(path, abs_builddir "/securityselinuxlabeldata/nfs/")) {
@@ -194,11 +182,7 @@ int setfilecon_raw(const char *path, security_context_t con)
constr, strlen(constr), 0);
}
-#ifdef SELINUX_CTX_CHAR_PTR
-int setfilecon(const char *path, const char *con)
-#else
-int setfilecon(const char *path, security_context_t con)
-#endif
+int setfilecon(const char *path, VIR_SELINUX_CTX_CONST char *con)
{
return setfilecon_raw(path, con);
}
--
1.7.9.2
10 years, 7 months
[libvirt] [PATCH v3] PCI: Introduce new device binding path using pci_dev.driver_override
by Alex Williamson
The driver_override field allows us to specify the driver for a device
rather than relying on the driver to provide a positive match of the
device. This shortcuts the existing process of looking up the vendor
and device ID, adding them to the driver new_id, binding the device,
then removing the ID, but it also provides a couple advantages.
First, the above existing process allows the driver to bind to any
device matching the new_id for the window where it's enabled. This is
often not desired, such as the case of trying to bind a single device
to a meta driver like pci-stub or vfio-pci. Using driver_override we
can do this deterministically using:
echo pci-stub > /sys/bus/pci/devices/0000:03:00.0/driver_override
echo 0000:03:00.0 > /sys/bus/pci/devices/0000:03:00.0/driver/unbind
echo 0000:03:00.0 > /sys/bus/pci/drivers_probe
Previously we could not invoke drivers_probe after adding a device
to new_id for a driver as we get non-deterministic behavior whether
the driver we intend or the standard driver will claim the device.
Now it becomes a deterministic process, only the driver matching
driver_override will probe the device.
To return the device to the standard driver, we simply clear the
driver_override and reprobe the device:
echo > /sys/bus/pci/devices/0000:03:00.0/driver_override
echo 0000:03:00.0 > /sys/bus/pci/devices/0000:03:00.0/driver/unbind
echo 0000:03:00.0 > /sys/bus/pci/drivers_probe
Another advantage to this approach is that we can specify a driver
override to force a specific binding or prevent any binding. For
instance when an IOMMU group is exposed to userspace through VFIO
we require that all devices within that group are owned by VFIO.
However, devices can be hot-added into an IOMMU group, in which case
we want to prevent the device from binding to any driver (override
driver = "none") or perhaps have it automatically bind to vfio-pci.
With driver_override it's a simple matter for this field to be set
internally when the device is first discovered to prevent driver
matches.
Signed-off-by: Alex Williamson <alex.williamson(a)redhat.com>
Cc: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
---
v3: kfree() override buffer on device release, noted by Alex Graf
v2: Use strchr() as suggested by Guenter Roeck and adopted by the
platform driver version of this same interface.
Documentation/ABI/testing/sysfs-bus-pci | 21 ++++++++++++++++
drivers/pci/pci-driver.c | 25 +++++++++++++++++--
drivers/pci/pci-sysfs.c | 40 +++++++++++++++++++++++++++++++
drivers/pci/probe.c | 1 +
include/linux/pci.h | 1 +
5 files changed, 85 insertions(+), 3 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
index a3c5a66..898ddc4 100644
--- a/Documentation/ABI/testing/sysfs-bus-pci
+++ b/Documentation/ABI/testing/sysfs-bus-pci
@@ -250,3 +250,24 @@ Description:
valid. For example, writing a 2 to this file when sriov_numvfs
is not 0 and not 2 already will return an error. Writing a 10
when the value of sriov_totalvfs is 8 will return an error.
+
+What: /sys/bus/pci/devices/.../driver_override
+Date: April 2014
+Contact: Alex Williamson <alex.williamson(a)redhat.com>
+Description:
+ This file allows the driver for a device to be specified which
+ will override standard static and dynamic ID matching. When
+ specified, only a driver with a name matching the value written
+ to driver_override will have an opportunity to bind to the
+ device. The override is specified by writing a string to the
+ driver_override file (echo pci-stub > driver_override) and
+ may be cleared with an empty string (echo > driver_override).
+ This returns the device to standard matching rules binding.
+ Writing to driver_override does not automatically unbind the
+ device from its current driver or make any attempt to
+ automatically load the specified driver. If no driver with a
+ matching name is currently loaded in the kernel, the device
+ will not bind to any driver. This also allows devices to
+ opt-out of driver binding using a driver_override name such as
+ "none". Only a single driver may be specified in the override,
+ there is no support for parsing delimiters.
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index d911e0c..4393c12 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -216,6 +216,13 @@ const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
return NULL;
}
+static const struct pci_device_id pci_device_id_any = {
+ .vendor = PCI_ANY_ID,
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+};
+
/**
* pci_match_device - Tell if a PCI device structure has a matching PCI device id structure
* @drv: the PCI driver to match against
@@ -229,18 +236,30 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv,
struct pci_dev *dev)
{
struct pci_dynid *dynid;
+ const struct pci_device_id *found_id = NULL;
+
+ /* When driver_override is set, only bind to the matching driver */
+ if (dev->driver_override && strcmp(dev->driver_override, drv->name))
+ return NULL;
/* Look at the dynamic ids first, before the static ones */
spin_lock(&drv->dynids.lock);
list_for_each_entry(dynid, &drv->dynids.list, node) {
if (pci_match_one_device(&dynid->id, dev)) {
- spin_unlock(&drv->dynids.lock);
- return &dynid->id;
+ found_id = &dynid->id;
+ break;
}
}
spin_unlock(&drv->dynids.lock);
- return pci_match_id(drv->id_table, dev);
+ if (!found_id)
+ found_id = pci_match_id(drv->id_table, dev);
+
+ /* driver_override will always match, send a dummy id */
+ if (!found_id && dev->driver_override)
+ found_id = &pci_device_id_any;
+
+ return found_id;
}
struct drv_dev_and_id {
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 4e0acef..faa4ab5 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -499,6 +499,45 @@ static struct device_attribute sriov_numvfs_attr =
sriov_numvfs_show, sriov_numvfs_store);
#endif /* CONFIG_PCI_IOV */
+static ssize_t driver_override_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ char *driver_override, *old = pdev->driver_override, *cp;
+
+ if (count > PATH_MAX)
+ return -EINVAL;
+
+ driver_override = kstrndup(buf, count, GFP_KERNEL);
+ if (!driver_override)
+ return -ENOMEM;
+
+ cp = strchr(driver_override, '\n');
+ if (cp)
+ *cp = '\0';
+
+ if (strlen(driver_override)) {
+ pdev->driver_override = driver_override;
+ } else {
+ kfree(driver_override);
+ pdev->driver_override = NULL;
+ }
+
+ kfree(old);
+
+ return count;
+}
+
+static ssize_t driver_override_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+
+ return sprintf(buf, "%s\n", pdev->driver_override);
+}
+static DEVICE_ATTR_RW(driver_override);
+
static struct attribute *pci_dev_attrs[] = {
&dev_attr_resource.attr,
&dev_attr_vendor.attr,
@@ -521,6 +560,7 @@ static struct attribute *pci_dev_attrs[] = {
#if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI)
&dev_attr_d3cold_allowed.attr,
#endif
+ &dev_attr_driver_override.attr,
NULL,
};
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index ef09f5f..54268de 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1215,6 +1215,7 @@ static void pci_release_dev(struct device *dev)
pci_release_of_node(pci_dev);
pcibios_release_device(pci_dev);
pci_bus_put(pci_dev->bus);
+ kfree(pci_dev->driver_override);
kfree(pci_dev);
}
diff --git a/include/linux/pci.h b/include/linux/pci.h
index aab57b4..b72af27 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -365,6 +365,7 @@ struct pci_dev {
#endif
phys_addr_t rom; /* Physical address of ROM if it's not from the BAR */
size_t romlen; /* Length of ROM if it's not from the BAR */
+ char *driver_override; /* Driver name to force a match */
};
static inline struct pci_dev *pci_physfn(struct pci_dev *dev)
10 years, 7 months