diff options
Diffstat (limited to 'lib/kobject.c')
| -rw-r--r-- | lib/kobject.c | 39 | 
1 files changed, 39 insertions, 0 deletions
diff --git a/lib/kobject.c b/lib/kobject.c index f07c57252e82..82dc34c095c2 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -746,17 +746,56 @@ void kset_unregister(struct kset *k)   */  struct kobject *kset_find_obj(struct kset *kset, const char *name)  { +	return kset_find_obj_hinted(kset, name, NULL); +} + +/** + * kset_find_obj_hinted - search for object in kset given a predecessor hint. + * @kset: kset we're looking in. + * @name: object's name. + * @hint: hint to possible object's predecessor. + * + * Check the hint's next object and if it is a match return it directly, + * otherwise, fall back to the behavior of kset_find_obj().  Either way + * a reference for the returned object is held and the reference on the + * hinted object is released. + */ +struct kobject *kset_find_obj_hinted(struct kset *kset, const char *name, +				     struct kobject *hint) +{  	struct kobject *k;  	struct kobject *ret = NULL;  	spin_lock(&kset->list_lock); + +	if (!hint) +		goto slow_search; + +	/* end of list detection */ +	if (hint->entry.next == kset->list.next) +		goto slow_search; + +	k = container_of(hint->entry.next, struct kobject, entry); +	if (!kobject_name(k) || strcmp(kobject_name(k), name)) +		goto slow_search; + +	ret = kobject_get(k); +	goto unlock_exit; + +slow_search:  	list_for_each_entry(k, &kset->list, entry) {  		if (kobject_name(k) && !strcmp(kobject_name(k), name)) {  			ret = kobject_get(k);  			break;  		}  	} + +unlock_exit:  	spin_unlock(&kset->list_lock); + +	if (hint) +		kobject_put(hint); +  	return ret;  }  |