Received: by 10.213.65.68 with SMTP id h4csp629818imn; Tue, 13 Mar 2018 15:40:46 -0700 (PDT) X-Google-Smtp-Source: AG47ELv9G73fDxEdrM59Qfd64D1JnbSKfKGnE3c/DjRXTysPIF13sMX80dbwCQJKLeEcUHM10EYo X-Received: by 10.98.65.72 with SMTP id o69mr2101560pfa.97.1520980846200; Tue, 13 Mar 2018 15:40:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1520980846; cv=none; d=google.com; s=arc-20160816; b=xXvrgcay01ukqliCHFoLBawUSiaWIEKElhnGRxT8Si4CtVww6qXG3537nIEONJjgg3 6Nir8+7WZtk7Qt7ngbwq8R/ekxZrMspl0rp6hsgxOXmpxZ1TL3mUbGqZG7fnjj6y1SFH Aez6bauQwfu2RfWRnBgR7taAHABoPkD0jge+cdv39EiESo8POCePud9Y9fFyr1DP1Z7a pY2of8mbEyfW6hptaBEGyWbxbWzJJQATjTAhcWNlx/OhYRa5nScBlSaQkumxVQVp7OIn c4j/F1iSRMKKJ6gVrvbgQCWhMLq/pLSdIv//c83f0Cse4Iz5eLIELVsfb5Ii46JW4wcP rVqw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:arc-authentication-results; bh=IuR4lnSCkL5BzJ5f/eJMf+W1msLb/o0OhUIduoOORE0=; b=C2Ots+by3N5ijcncF8K2RtpJnSnt4AwrJMpQqdddfNAW6OpEj2U/8ZWn/HDdVRyzv3 yY5nTbABXLwXkJs0beSPscqIPGVRttyAhosF6qZQFHcLZYpE+NhyJCuuRWLCp8AQ7z06 9fksC4+Kmdwp+ucmRVhlBoVmjJE7P5jJMOTKjvOe1FCNAwWTv6w9DyKk2LodJ9TDyHYD rdoP/W9hiexJ3XSg5pEIEqgB4qM4nDAjIAlVmJgqj4IetuFOKG9wYkfa8HWNGMWnhzWK zA8YdyLFd+/FP0I0vmQahPO92g7h93k2865xIPhkVd3o9P9jCV2X8F6Oau86OHyeAzHh SQMw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p1-v6si836539plb.297.2018.03.13.15.40.32; Tue, 13 Mar 2018 15:40:46 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932360AbeCMWib (ORCPT + 99 others); Tue, 13 Mar 2018 18:38:31 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:50486 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752729AbeCMWia (ORCPT ); Tue, 13 Mar 2018 18:38:30 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CDCEC8424C; Tue, 13 Mar 2018 22:38:29 +0000 (UTC) Received: from treble (ovpn-122-218.rdu2.redhat.com [10.10.122.218]) by smtp.corp.redhat.com (Postfix) with SMTP id 542E72026DFD; Tue, 13 Mar 2018 22:38:29 +0000 (UTC) Date: Tue, 13 Mar 2018 17:38:29 -0500 From: Josh Poimboeuf To: Petr Mladek Cc: Jiri Kosina , Miroslav Benes , Jason Baron , Joe Lawrence , Jessica Yu , Evgenii Shatokhin , live-patching@vger.kernel.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH v10 01/10] livepatch: Use lists to manage patches, objects and functions Message-ID: <20180313223829.fjpehbvzpmoehkby@treble> References: <20180307082039.10196-1-pmladek@suse.com> <20180307082039.10196-2-pmladek@suse.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <20180307082039.10196-2-pmladek@suse.com> User-Agent: Mutt/1.6.0.1 (2016-04-01) X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Tue, 13 Mar 2018 22:38:29 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Tue, 13 Mar 2018 22:38:29 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'jpoimboe@redhat.com' RCPT:'' Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, Mar 07, 2018 at 09:20:30AM +0100, Petr Mladek wrote: > From: Jason Baron > > Currently klp_patch contains a pointer to a statically allocated array of > struct klp_object and struct klp_objects contains a pointer to a statically > allocated array of klp_func. In order to allow for the dynamic allocation > of objects and functions, link klp_patch, klp_object, and klp_func together > via linked lists. This allows us to more easily allocate new objects and > functions, while having the iterator be a simple linked list walk. > > The static structures are added to the lists early. It allows to add > the dynamically allocated objects before klp_init_object() and > klp_init_func() calls. Therefore it reduces the further changes > to the code. > > Also klp_init_*_list() functions are split because they will > be used when adding the dynamically allocated structures. > > This patch does not change the existing behavior. > > Signed-off-by: Jason Baron > [pmladek@suse.com: Initialize lists before init calls] > Signed-off-by: Petr Mladek > Cc: Josh Poimboeuf > Cc: Jessica Yu > Cc: Jiri Kosina > Acked-by: Miroslav Benes > --- > include/linux/livepatch.h | 19 +++++++++++++++++-- > kernel/livepatch/core.c | 27 +++++++++++++++++++++++++++ > 2 files changed, 44 insertions(+), 2 deletions(-) > > diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h > index 4754f01c1abb..e5db2ba7e2a5 100644 > --- a/include/linux/livepatch.h > +++ b/include/linux/livepatch.h > @@ -24,6 +24,7 @@ > #include > #include > #include > +#include > > #if IS_ENABLED(CONFIG_LIVEPATCH) > > @@ -43,6 +44,7 @@ > * @old_addr: the address of the function being patched > * @kobj: kobject for sysfs resources > * @stack_node: list node for klp_ops func_stack list > + * @func_entry: links struct klp_func to struct klp_object For consistency with 'stack_node', I think the field should have 'node' in the name. Also, putting 'func' in the name is redundant because the struct already has 'func' in its name. IMO, just 'node' would be good. I also found the description to be confusing. How about something similar to the 'stack_node' description: * @node: list node for klp_object func list > * @old_size: size of the old function > * @new_size: size of the new function > * @patched: the func has been added to the klp_ops list > @@ -80,6 +82,7 @@ struct klp_func { > unsigned long old_addr; > struct kobject kobj; > struct list_head stack_node; > + struct list_head func_entry; > unsigned long old_size, new_size; > bool patched; > bool transition; > @@ -117,6 +120,8 @@ struct klp_callbacks { > * @kobj: kobject for sysfs resources > * @mod: kernel module associated with the patched object > * (NULL for vmlinux) > + * @func_list: head of list for struct klp_func > + * @obj_entry: links struct klp_object to struct klp_patch Similar comments here. > * @patched: the object's funcs have been added to the klp_ops list > */ > struct klp_object { > @@ -127,6 +132,8 @@ struct klp_object { > > /* internal */ > struct kobject kobj; > + struct list_head func_list; > + struct list_head obj_entry; > struct module *mod; > bool patched; > }; > @@ -137,6 +144,7 @@ struct klp_object { > * @objs: object entries for kernel objects to be patched > * @list: list node for global list of registered patches > * @kobj: kobject for sysfs resources > + * @obj_list: head of list for struct klp_object > * @enabled: the patch is enabled (but operation may be incomplete) > * @finish: for waiting till it is safe to remove the patch module > */ > @@ -148,18 +156,25 @@ struct klp_patch { > /* internal */ > struct list_head list; > struct kobject kobj; > + struct list_head obj_list; > bool enabled; > struct completion finish; > }; > > -#define klp_for_each_object(patch, obj) \ > +#define klp_for_each_object_static(patch, obj) \ > for (obj = patch->objs; obj->funcs || obj->name; obj++) > > -#define klp_for_each_func(obj, func) \ > +#define klp_for_each_object(patch, obj) \ > + list_for_each_entry(obj, &patch->obj_list, obj_entry) > + > +#define klp_for_each_func_static(obj, func) \ > for (func = obj->funcs; \ > func->old_name || func->new_func || func->old_sympos; \ > func++) > > +#define klp_for_each_func(obj, func) \ > + list_for_each_entry(func, &obj->func_list, func_entry) > + > int klp_register_patch(struct klp_patch *); > int klp_unregister_patch(struct klp_patch *); > int klp_enable_patch(struct klp_patch *); > diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c > index 3a4656fb7047..1d525f4a270a 100644 > --- a/kernel/livepatch/core.c > +++ b/kernel/livepatch/core.c > @@ -49,6 +49,32 @@ static LIST_HEAD(klp_patches); > > static struct kobject *klp_root_kobj; > > +static void klp_init_func_list(struct klp_object *obj, struct klp_func *func) > +{ > + list_add(&func->func_entry, &obj->func_list); > +} This function is confusingly named. It *adds* to the func list instead of initializing it. Also, I think wrapping a single list_add() in a function makes the calling code harder to read and understand. I would suggest getting rid of the function altogether and just inlining the list_add(). I also found the code harder to read in several other places, for similar reasons (several small single-use functions). I call it functionitis :-) > + > +static void klp_init_object_list(struct klp_patch *patch, > + struct klp_object *obj) > +{ > + struct klp_func *func; > + > + list_add(&obj->obj_entry, &patch->obj_list); > + > + INIT_LIST_HEAD(&obj->func_list); > + klp_for_each_func_static(obj, func) > + klp_init_func_list(obj, func); > +} > + > +static void klp_init_patch_list(struct klp_patch *patch) > +{ > + struct klp_object *obj; > + > + INIT_LIST_HEAD(&patch->obj_list); > + klp_for_each_object_static(patch, obj) > + klp_init_object_list(patch, obj); > +} klp_init_patch_list() can be a confusing name. To me it sounds like a list of patches. But really it's a list of objects. The same goes for klp_init_object_list(). What if we just call it klp_init_lists(), and move klp_init_object_list() inline? I know a later patch also adds a call to klp_init_object_list() from klp_get_or_add_object(), but I think it should be inlined there as well, because all that function needs to do is the list_add() and the INIT_LIST_HEAD() -- the object is freshly allocated so it doesn't need to copy any funcs to the list. IMO it's more readable and more explicit to repeat the few minor and obvious lines of code than to hide them in a wrapper function which also does other things for other callers. All this will help with some of the functionitis-related readability issues, IMO. > + > static bool klp_is_module(struct klp_object *obj) > { > return obj->name; > @@ -794,6 +820,7 @@ static int klp_init_patch(struct klp_patch *patch) > > patch->enabled = false; > init_completion(&patch->finish); > + klp_init_patch_list(patch); > > ret = kobject_init_and_add(&patch->kobj, &klp_ktype_patch, > klp_root_kobj, "%s", patch->mod->name); > -- > 2.13.6 > -- Josh