Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752588AbdHNN42 (ORCPT ); Mon, 14 Aug 2017 09:56:28 -0400 Received: from mx1.redhat.com ([209.132.183.28]:17952 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751141AbdHNN41 (ORCPT ); Mon, 14 Aug 2017 09:56:27 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 343197E45B Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=joe.lawrence@redhat.com Subject: Re: [PATCH v3] livepatch: introduce shadow variable API To: Josh Poimboeuf Cc: live-patching@vger.kernel.org, linux-kernel@vger.kernel.org, Jessica Yu , Jiri Kosina , Miroslav Benes , Petr Mladek References: <1501262722-26502-1-git-send-email-joe.lawrence@redhat.com> <1501262722-26502-2-git-send-email-joe.lawrence@redhat.com> <20170811163511.psyran7h2zvsxtfk@treble> From: Joe Lawrence Organization: Red Hat Message-ID: <2ed6354d-9724-674e-7903-8ed3900197dc@redhat.com> Date: Mon, 14 Aug 2017 09:56:24 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.2.0 MIME-Version: 1.0 In-Reply-To: <20170811163511.psyran7h2zvsxtfk@treble> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Mon, 14 Aug 2017 13:56:27 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3631 Lines: 114 On 08/11/2017 12:35 PM, Josh Poimboeuf wrote: > On Fri, Jul 28, 2017 at 01:25:22PM -0400, Joe Lawrence wrote: >> Add exported API for livepatch modules: >> >> klp_shadow_get() >> klp_shadow_attach() >> klp_shadow_get_or_attach() >> klp_shadow_update_or_attach() >> klp_shadow_detach() >> klp_shadow_detach_all() > > I like the API. > >> +Matching parent's lifecycle >> +--------------------------- >> + >> +If parent data structures are frequently created and destroyed, it may >> +be easiest to align its shadow variable lifetimes to the same allocation > > "its shadow variable lifetimes" -> "their shadow variables' lifetimes" ? "parent data structures" is plural, so I think you are correct. >> +void *klp_shadow_attach(void *obj, unsigned long id, void *data, >> + size_t size, gfp_t gfp_flags) > > [ Note: some of the following comments also apply to > klp_shadow_get_or_attach and klp_shadow_update_or_attach. ] > >> +{ >> + struct klp_shadow *new_shadow; > > nit: The "new" is implied, and there's only one shadow struct used in > the function, so maybe just call it "shadow"? I'd like to keep the "new_" prefix convention to clearly mark that structure as a (temporarily) allocated one. v4 WIP modifies klp_shadow_update_or_attach() to include both "new_shadow" and "shadow", so there will be a convention established there. >> + void *shadow_data; >> + unsigned long flags; >> + >> + /* Take error exit path if already exists */ >> + shadow_data = klp_shadow_get(obj, id); >> + if (unlikely(shadow_data)) >> + goto err_exists; > > The return value of klp_shadow_get() can be tested directly, no need for > a variable. Yup. > >> + /* Allocate a new shadow variable for use inside the lock below */ >> + new_shadow = kzalloc(size + sizeof(*new_shadow), gfp_flags); >> + if (!new_shadow) >> + goto err; > > The goto destination is just a single line return, so I think it's > clearer to just return NULL here and get rid of the err label. Yeah, in isolation I'd agree with you, however I chose to error on the side of the overall pattern: klp_shadow_attach(), klp_shadow_get_or_attach(), and klp_shadow_update_or_attach() all follow the same structure. It felt more consistent to maintain similar exit patterns and bend this style rule. Either way, the point is moot as fixing the problems Miroslav pointed out (and below) required refactoring these routines and their return paths. >> + >> + /* Look for again under the lock */ >> + spin_lock_irqsave(&klp_shadow_lock, flags); >> + shadow_data = klp_shadow_get(obj, id); >> + if (unlikely(shadow_data)) { >> + >> + /* Shadow variable found, throw away allocation and take >> + * error exit path */ > > Multi-line comments should be in the kernel coding style: > > /* > * Shadow variable found, throw away allocation and take > * error exit path > */ > > Also, complete sentences preferred :-) Looks like someone forgot to run through checkpatch. Sorry about that. > >> + spin_unlock_irqrestore(&klp_shadow_lock, flags); >> + kfree(shadow_data); > > Shouldn't it free new_shadow instead of shadow_data? You are correct ... will fix in v4. >> + goto err_exists; >> + } >> + >> + /* No found, add the newly allocated one */ >> + shadow_data = data; >> + klp_shadow_set(new_shadow, obj, id, data, size); > > To avoid doing extra work with the lock held, the klp_shadow_set() can > be done before getting the lock, after the kzalloc. The interesting work being a potentially speculative memcpy... moving outside the lock, after the first search-miss, makes sense. Thanks, -- Joe