From: Don Dutile <ddutile@redhat.com> Date: Fri, 24 Apr 2009 14:31:02 -0400 Subject: [misc] make bus_find_device more robust, match upstream Message-id: 49F20566.7030505@redhat.com O-Subject: Re: [RHEL5.4 PATCH V2] Make bus_find_device() more robust to match upstream KVM device assignment use Bugzilla: 492488 RH-Acked-by: Rik van Riel <riel@redhat.com> RH-Acked-by: Markus Armbruster <armbru@redhat.com> Don Dutile wrote: > BZ 492488 > > The following 3 file patch is a backport of the following > 2 upstream patches. The patch enables the following to > work: > echo 0000:01:00.0 > /sys/bus/pci/devices/0000:01:00.0/driver/unbind > > and not require a "-n" in the echo command to > strip the trailing newline. > > This enables upstream scripts designed to do KVM device assignment > to work on RHEL5 w/o adding a bunch of "-n" 's to these type of echo statements. > > Only built on x86_64 kernel. > (it's architecture neutral). > (sorry, no brew build since it was so trivial...). > > > Tested during device assignments tests with VT-D testing on RHEL5.4. > -- unbound a PCIe e1000e NIC card from a rhel5.4 host; > -- bound the e1000e device to a rhel5.3 guest > > > Upstream patches: > (1) http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=34990cf702 > > Add a new sysfs_streq() string comparison function, which ignores > the trailing newlines found in sysfs inputs. By example: > > sysfs_streq("a", "b") ==> false > sysfs_streq("a", "a") ==> true > sysfs_streq("a", "a\n") ==> true > sysfs_streq("a\n", "a") ==> true > > This is intended to simplify parsing of sysfs inputs, letting them > avoid the need to manually strip off newlines from inputs. > > Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> > Acked-by: Greg KH <greg@kroah.com> > Signed-off-by: Andrew Morton <akpm@linux-foundation.org> > Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> > > > (2) http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=3ce24d8d93 > > Use sysfs_streq() in bus_find_device_by_name() so trailing newlines > are ignored (E.G. in bind/unbind). > > Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk> > Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> > > > NOTE: bus_find_device_by_name() is "driver_helper()" in RHEL5's driver/base/bus.c module. > Since the first 3 reviewers didn't like the format, tweaked it to match upstream. ... a simple edit, as the original was. Please (re-)review & ACK. - Don diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 2beb313..6f7d9f5 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -141,9 +141,7 @@ static int driver_helper(struct device *dev, void *data) { const char *name = data; - if (strcmp(name, dev->bus_id) == 0) - return 1; - return 0; + return sysfs_streq(name, dev->bus_id); } static ssize_t driver_unbind(struct device_driver *drv, diff --git a/include/linux/string.h b/include/linux/string.h index 7c88844..e5cc255 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -113,5 +113,7 @@ extern void argv_free(char **argv); } #endif +extern bool sysfs_streq(const char *s1, const char *s2); + #endif #endif /* _LINUX_STRING_H_ */ diff --git a/lib/string.c b/lib/string.c index cbae612..479bc84 100644 --- a/lib/string.c +++ b/lib/string.c @@ -495,6 +495,33 @@ char *strsep(char **s, const char *ct) EXPORT_SYMBOL(strsep); #endif +/** + * sysfs_streq - return true if strings are equal, modulo trailing newline + * @s1: one string + * @s2: another string + * + * This routine returns true iff two strings are equal, treating both + * NUL and newline-then-NUL as equivalent string terminations. It's + * geared for use with sysfs input strings, which generally terminate + * with newlines but are compared against values without newlines. + */ +bool sysfs_streq(const char *s1, const char *s2) +{ + while (*s1 && *s1 == *s2) { + s1++; + s2++; + } + + if (*s1 == *s2) + return true; + if (!*s1 && *s2 == '\n' && !s2[1]) + return true; + if (*s1 == '\n' && !s1[1] && !*s2) + return true; + return false; +} +EXPORT_SYMBOL(sysfs_streq); + #ifndef __HAVE_ARCH_MEMSET /** * memset - Fill a region of memory with the given value