From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id EF3BACD80BA for ; Tue, 10 Oct 2023 12:10:58 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 83E528D00B7; Tue, 10 Oct 2023 08:10:58 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 7EC1E8D0002; Tue, 10 Oct 2023 08:10:58 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 6B4268D00B7; Tue, 10 Oct 2023 08:10:58 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id 5B7A18D0002 for ; Tue, 10 Oct 2023 08:10:58 -0400 (EDT) Received: from smtpin14.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id 265468037D for ; Tue, 10 Oct 2023 12:10:58 +0000 (UTC) X-FDA: 81329435796.14.7CC4B09 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.9]) by imf02.hostedemail.com (Postfix) with ESMTP id 8886E80017 for ; Tue, 10 Oct 2023 12:10:55 +0000 (UTC) Authentication-Results: imf02.hostedemail.com; dkim=pass header.d=intel.com header.s=Intel header.b=If0dsoIY; spf=none (imf02.hostedemail.com: domain of andi.shyti@linux.intel.com has no SPF policy when checking 198.175.65.9) smtp.mailfrom=andi.shyti@linux.intel.com; dmarc=pass (policy=none) header.from=intel.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1696939856; a=rsa-sha256; cv=none; b=0HCJNCA/6Nb8+Y37x3otAvkm5+YO7YKzkwU++/OhcuHmPOnL0BHgxxm8mTh+Hmk/3RL5rB hmpG47Ov8kl28wd7Dh1w+ff73oDfqHzmvl8a1vbKU6oqerWPIsOKptgfReECmAjkR4sq2e Rjzi9QiO9MCKae2v0c3Er7NCUSeCxYU= ARC-Authentication-Results: i=1; imf02.hostedemail.com; dkim=pass header.d=intel.com header.s=Intel header.b=If0dsoIY; spf=none (imf02.hostedemail.com: domain of andi.shyti@linux.intel.com has no SPF policy when checking 198.175.65.9) smtp.mailfrom=andi.shyti@linux.intel.com; dmarc=pass (policy=none) header.from=intel.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1696939856; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=cx+fLKByRvI55bqXt68TlBzhyJoWvCr7nBk1KshlI2M=; b=Pbv1Gztkv7b50yJFaL0qLKkX7gZQmirc+W/IqxWEhek+whrHArDUTVRv7P6ipS1r2lCtBv 8gtyEv68+wD7VA7e7GvHiHIh1scgwhjC/EblF3xzVUNDRDbNhDAwKkCQdlpSUGudnvMDM7 Ppfluc6IM6m5+gLCIx0OMX5pbEbUJ/U= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1696939855; x=1728475855; h=date:from:to:cc:subject:message-id:references: mime-version:in-reply-to; bh=MhzqtUQNYcDXM0Qwafp8sxgn/nGKfGWW2YYmcm211do=; b=If0dsoIYY9C5Z9uVp7jrPTcbcDjyt3iHkLRxrzAlGHHDVITZ49/+n0PD N8vN5uTTzMRJ5yZgpITe8ZYmi5mFKb8Gq7nH+0LrTIvECZirgB3DOoisp j94ns8v57D7s615LsgJ1WstiZ0f4RnZE1a9gailMdXZIbCzzY3l/XvRg4 CKdy7zXrBrVpFvt8bBFR42+263rxE5T6F1Xhoh+1qoPQZOTJK9nbR04WG src0IrrUfL2mt4v/t++ZaFCB41o5ONDO4d6V6JFWUDCOCT3VcBMg7z6Ft +tmgKUr8KpUOJ1rQPA7vAk9sNqGXSGz49QCdiDgNGMrIqwXGGV5EawD/A Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10858"; a="2965881" X-IronPort-AV: E=Sophos;i="6.03,212,1694761200"; d="scan'208";a="2965881" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orvoesa101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Oct 2023 05:10:53 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10859"; a="823755667" X-IronPort-AV: E=Sophos;i="6.03,212,1694761200"; d="scan'208";a="823755667" Received: from ppalanyk-mobl.gar.corp.intel.com (HELO intel.com) ([10.213.148.82]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Oct 2023 05:10:48 -0700 Date: Tue, 10 Oct 2023 14:10:36 +0200 From: Andi Shyti To: Andrzej Hajda Cc: linux-kernel@vger.kernel.org, intel-gfx@lists.freedesktop.org, linux-mm@kvack.org, Thomas Gleixner , Andi Shyti , Nirmoy Das , Janusz Krzysztofik Subject: Re: [PATCH v2] debugobjects: stop accessing objects after releasing spinlock Message-ID: References: <20230925131359.2948827-1-andrzej.hajda@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: X-Rspamd-Server: rspam08 X-Rspamd-Queue-Id: 8886E80017 X-Stat-Signature: ootqras79yqrjsoztwpsfaqkzbu5cn5i X-Rspam-User: X-HE-Tag: 1696939855-105829 X-HE-Meta: U2FsdGVkX1+PfOcnkIdM6AYKs7cP0ZQ11kPIYrn0oo4XPLBJOkk3IBb/JuE009EXSvCES+H1nHuVpxx4pnSrP8Crm9Yl74QUKD7V5547boXokbp9uZ33JjMTfuXYvg7WT7WZqac5NUm96iNieBdmMgjiw6ox+jeX/TxoppYk7HYpk9q1+ezBssltAB4WGbqcLZ9fhSCDmKefadSogg2oTo6UcaFOyq2Pqc+jLjonsabUosincUYv03zioRomRDbQxXhWvQJ0HHmmiLjT5eO8t/TNs6qLTLssusX5LJ1bnbipGnErN63pAn5QmvRJEmuVJS331nGvHpdl2/5z6NsNXDTuRNWkZ1FNMoJKymnQt/iOa1j7Cc34vvu8f6vY4YxkUwSd74GQZ4Q+JLMaQgc/X5mmUs9Qv1Unb5+SEkEUu6/TOKXcf7Qp/fBdJ24ysDO9SqX1vyS1NPfPooMM8mwOi4P16Um4tyvhX6e100u8yKnWM7DytaEIxGDpOZNUdNPqtFX5H5BBvWR4AyGFRiSdHpJ/pPjwrQ9uwE+oqFAnwPECqzv+0rM1Ym6j9HWpm7lAwUtH4poHgVQ0iSICqbmDDGxolxGLksFIwB0aeAAf3+zjOk5Dzm7PBe3wPJki29W/9jcwmB3ysSsoAkri/7GyKipesagLjt3/UBeacBcinkB+syBS5SdvYNzhKw/ILug6MSfxwVn2wxfhQVJko5rz0v5Kht92V0LEPyNOlMAD78cPuiCwDaqdIujFEtUdd9wuGQAhcYyYFbPlCv6nLdEDm42cNwVGHjP6nTH3KU7Hk4pj09lRgs0/EKcr/FYIL/YGC4bntiaaq5HUzVuvsap3ycuK7x071inw8yybLZBbvDknsYWudcAMs//LQSR90FI68zGgqcYMyrwOdKpGwCZ81ehi7UEBRdjR8GNTJHEaKqxgz4ECS4cc04iLAEKStglM/SjpEX9oLGcVI+hUm6w 8z62Ic7s yWU7zHtwPTAIssDMBJP3crAptjreQwlhcjba9lVmBGx3ZsQytXxJFbSmGpga9bKxP9JM3qEYhVgx8B+J24JD/fhrFCHoEyWvGrC8BT8Piy6O13gY= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Hi Andrzej, On Tue, Oct 10, 2023 at 02:02:54PM +0200, Andrzej Hajda wrote: > On 25.09.2023 15:13, Andrzej Hajda wrote: > > After spinlock release object can be modified/freed by concurrent thread. > > Using it in such case is error prone, even for printing object state. > > To avoid such situation local copy of the object is created if necessary. > > > > Signed-off-by: Andrzej Hajda > > --- > > v2: add missing switch breaks > > --- > > Ping, any volunteer to review? ops... sorry... this slipped from my review list. Will look at it soon Andi > Regards > Andrzej > > > > > > lib/debugobjects.c | 206 +++++++++++++++++++++------------------------ > > 1 file changed, 97 insertions(+), 109 deletions(-) > > > > diff --git a/lib/debugobjects.c b/lib/debugobjects.c > > index a517256a270b71..3afff2f668fc1e 100644 > > --- a/lib/debugobjects.c > > +++ b/lib/debugobjects.c > > @@ -620,9 +620,8 @@ static void debug_objects_fill_pool(void) > > static void > > __debug_object_init(void *addr, const struct debug_obj_descr *descr, int onstack) > > { > > - enum debug_obj_state state; > > struct debug_bucket *db; > > - struct debug_obj *obj; > > + struct debug_obj *obj, o; > > unsigned long flags; > > debug_objects_fill_pool(); > > @@ -644,23 +643,19 @@ __debug_object_init(void *addr, const struct debug_obj_descr *descr, int onstack > > case ODEBUG_STATE_INACTIVE: > > obj->state = ODEBUG_STATE_INIT; > > break; > > - > > - case ODEBUG_STATE_ACTIVE: > > - state = obj->state; > > - raw_spin_unlock_irqrestore(&db->lock, flags); > > - debug_print_object(obj, "init"); > > - debug_object_fixup(descr->fixup_init, addr, state); > > - return; > > - > > - case ODEBUG_STATE_DESTROYED: > > - raw_spin_unlock_irqrestore(&db->lock, flags); > > - debug_print_object(obj, "init"); > > - return; > > default: > > - break; > > + o = *obj; > > + obj = NULL; > > } > > raw_spin_unlock_irqrestore(&db->lock, flags); > > + > > + if (obj) > > + return; > > + > > + debug_print_object(&o, "init"); > > + if (o.state == ODEBUG_STATE_ACTIVE) > > + debug_object_fixup(descr->fixup_init, addr, o.state); > > } > > /** > > @@ -700,12 +695,9 @@ EXPORT_SYMBOL_GPL(debug_object_init_on_stack); > > */ > > int debug_object_activate(void *addr, const struct debug_obj_descr *descr) > > { > > - struct debug_obj o = { .object = addr, .state = ODEBUG_STATE_NOTAVAILABLE, .descr = descr }; > > - enum debug_obj_state state; > > struct debug_bucket *db; > > - struct debug_obj *obj; > > + struct debug_obj *obj, o; > > unsigned long flags; > > - int ret; > > if (!debug_objects_enabled) > > return 0; > > @@ -717,49 +709,47 @@ int debug_object_activate(void *addr, const struct debug_obj_descr *descr) > > raw_spin_lock_irqsave(&db->lock, flags); > > obj = lookup_object_or_alloc(addr, db, descr, false, true); > > - if (likely(!IS_ERR_OR_NULL(obj))) { > > - bool print_object = false; > > - > > + if (unlikely(!obj)) { > > + raw_spin_unlock_irqrestore(&db->lock, flags); > > + debug_objects_oom(); > > + return 0; > > + } else if (likely(!IS_ERR(obj))) { > > switch (obj->state) { > > case ODEBUG_STATE_INIT: > > case ODEBUG_STATE_INACTIVE: > > obj->state = ODEBUG_STATE_ACTIVE; > > - ret = 0; > > break; > > - > > case ODEBUG_STATE_ACTIVE: > > - state = obj->state; > > - raw_spin_unlock_irqrestore(&db->lock, flags); > > - debug_print_object(obj, "activate"); > > - ret = debug_object_fixup(descr->fixup_activate, addr, state); > > - return ret ? 0 : -EINVAL; > > - > > case ODEBUG_STATE_DESTROYED: > > - print_object = true; > > - ret = -EINVAL; > > + o = *obj; > > + obj = NULL; > > break; > > default: > > - ret = 0; > > break; > > } > > - raw_spin_unlock_irqrestore(&db->lock, flags); > > - if (print_object) > > - debug_print_object(obj, "activate"); > > - return ret; > > + } else { > > + o.object = addr; > > + o.state = ODEBUG_STATE_NOTAVAILABLE; > > + o.descr = descr; > > + obj = NULL; > > } > > raw_spin_unlock_irqrestore(&db->lock, flags); > > - /* If NULL the allocation has hit OOM */ > > - if (!obj) { > > - debug_objects_oom(); > > + if (obj) > > return 0; > > - } > > - /* Object is neither static nor tracked. It's not initialized */ > > debug_print_object(&o, "activate"); > > - ret = debug_object_fixup(descr->fixup_activate, addr, ODEBUG_STATE_NOTAVAILABLE); > > - return ret ? 0 : -EINVAL; > > + > > + switch (o.state) { > > + case ODEBUG_STATE_ACTIVE: > > + case ODEBUG_STATE_NOTAVAILABLE: > > + if (debug_object_fixup(descr->fixup_activate, addr, o.state)) > > + return 0; > > + fallthrough; > > + default: > > + return -EINVAL; > > + } > > } > > EXPORT_SYMBOL_GPL(debug_object_activate); > > @@ -771,9 +761,8 @@ EXPORT_SYMBOL_GPL(debug_object_activate); > > void debug_object_deactivate(void *addr, const struct debug_obj_descr *descr) > > { > > struct debug_bucket *db; > > - struct debug_obj *obj; > > + struct debug_obj *obj, o; > > unsigned long flags; > > - bool print_object = false; > > if (!debug_objects_enabled) > > return; > > @@ -788,30 +777,29 @@ void debug_object_deactivate(void *addr, const struct debug_obj_descr *descr) > > case ODEBUG_STATE_INIT: > > case ODEBUG_STATE_INACTIVE: > > case ODEBUG_STATE_ACTIVE: > > - if (!obj->astate) > > + if (!obj->astate) { > > obj->state = ODEBUG_STATE_INACTIVE; > > - else > > - print_object = true; > > - break; > > - > > + break; > > + } > > + fallthrough; > > case ODEBUG_STATE_DESTROYED: > > - print_object = true; > > + o = *obj; > > + obj = NULL; > > break; > > default: > > break; > > } > > + } else { > > + o.object = addr; > > + o.state = ODEBUG_STATE_NOTAVAILABLE; > > + o.descr = descr; > > + obj = NULL; > > } > > raw_spin_unlock_irqrestore(&db->lock, flags); > > - if (!obj) { > > - struct debug_obj o = { .object = addr, > > - .state = ODEBUG_STATE_NOTAVAILABLE, > > - .descr = descr }; > > + if (!obj) > > debug_print_object(&o, "deactivate"); > > - } else if (print_object) { > > - debug_print_object(obj, "deactivate"); > > - } > > } > > EXPORT_SYMBOL_GPL(debug_object_deactivate); > > @@ -822,11 +810,9 @@ EXPORT_SYMBOL_GPL(debug_object_deactivate); > > */ > > void debug_object_destroy(void *addr, const struct debug_obj_descr *descr) > > { > > - enum debug_obj_state state; > > struct debug_bucket *db; > > - struct debug_obj *obj; > > + struct debug_obj *obj, o; > > unsigned long flags; > > - bool print_object = false; > > if (!debug_objects_enabled) > > return; > > @@ -836,8 +822,10 @@ void debug_object_destroy(void *addr, const struct debug_obj_descr *descr) > > raw_spin_lock_irqsave(&db->lock, flags); > > obj = lookup_object(addr, db); > > - if (!obj) > > - goto out_unlock; > > + if (!obj) { > > + raw_spin_unlock_irqrestore(&db->lock, flags); > > + return; > > + } > > switch (obj->state) { > > case ODEBUG_STATE_NONE: > > @@ -846,22 +834,23 @@ void debug_object_destroy(void *addr, const struct debug_obj_descr *descr) > > obj->state = ODEBUG_STATE_DESTROYED; > > break; > > case ODEBUG_STATE_ACTIVE: > > - state = obj->state; > > - raw_spin_unlock_irqrestore(&db->lock, flags); > > - debug_print_object(obj, "destroy"); > > - debug_object_fixup(descr->fixup_destroy, addr, state); > > - return; > > - > > case ODEBUG_STATE_DESTROYED: > > - print_object = true; > > + o = *obj; > > + obj = NULL; > > break; > > default: > > break; > > } > > -out_unlock: > > + > > raw_spin_unlock_irqrestore(&db->lock, flags); > > - if (print_object) > > - debug_print_object(obj, "destroy"); > > + > > + if (obj) > > + return; > > + > > + debug_print_object(&o, "destroy"); > > + > > + if (o.state == ODEBUG_STATE_ACTIVE) > > + debug_object_fixup(descr->fixup_destroy, addr, o.state); > > } > > EXPORT_SYMBOL_GPL(debug_object_destroy); > > @@ -872,9 +861,8 @@ EXPORT_SYMBOL_GPL(debug_object_destroy); > > */ > > void debug_object_free(void *addr, const struct debug_obj_descr *descr) > > { > > - enum debug_obj_state state; > > struct debug_bucket *db; > > - struct debug_obj *obj; > > + struct debug_obj *obj, o; > > unsigned long flags; > > if (!debug_objects_enabled) > > @@ -885,24 +873,29 @@ void debug_object_free(void *addr, const struct debug_obj_descr *descr) > > raw_spin_lock_irqsave(&db->lock, flags); > > obj = lookup_object(addr, db); > > - if (!obj) > > - goto out_unlock; > > + if (!obj) { > > + raw_spin_unlock_irqrestore(&db->lock, flags); > > + return; > > + } > > switch (obj->state) { > > case ODEBUG_STATE_ACTIVE: > > - state = obj->state; > > - raw_spin_unlock_irqrestore(&db->lock, flags); > > - debug_print_object(obj, "free"); > > - debug_object_fixup(descr->fixup_free, addr, state); > > - return; > > + o = *obj; > > + obj = NULL; > > + break; > > default: > > hlist_del(&obj->node); > > - raw_spin_unlock_irqrestore(&db->lock, flags); > > + } > > + > > + raw_spin_unlock_irqrestore(&db->lock, flags); > > + > > + if (obj) { > > free_object(obj); > > return; > > } > > -out_unlock: > > - raw_spin_unlock_irqrestore(&db->lock, flags); > > + > > + debug_print_object(&o, "free"); > > + debug_object_fixup(descr->fixup_free, addr, o.state); > > } > > EXPORT_SYMBOL_GPL(debug_object_free); > > @@ -955,9 +948,8 @@ debug_object_active_state(void *addr, const struct debug_obj_descr *descr, > > unsigned int expect, unsigned int next) > > { > > struct debug_bucket *db; > > - struct debug_obj *obj; > > + struct debug_obj *obj, o; > > unsigned long flags; > > - bool print_object = false; > > if (!debug_objects_enabled) > > return; > > @@ -970,28 +962,27 @@ debug_object_active_state(void *addr, const struct debug_obj_descr *descr, > > if (obj) { > > switch (obj->state) { > > case ODEBUG_STATE_ACTIVE: > > - if (obj->astate == expect) > > + if (obj->astate == expect) { > > obj->astate = next; > > - else > > - print_object = true; > > - break; > > - > > + break; > > + } > > + fallthrough; > > default: > > - print_object = true; > > + o = *obj; > > + obj = NULL; > > break; > > } > > + } else { > > + o.object = addr; > > + o.state = ODEBUG_STATE_NOTAVAILABLE; > > + o.descr = descr; > > + obj = NULL; > > } > > raw_spin_unlock_irqrestore(&db->lock, flags); > > - if (!obj) { > > - struct debug_obj o = { .object = addr, > > - .state = ODEBUG_STATE_NOTAVAILABLE, > > - .descr = descr }; > > + if (!obj) > > debug_print_object(&o, "active_state"); > > - } else if (print_object) { > > - debug_print_object(obj, "active_state"); > > - } > > } > > EXPORT_SYMBOL_GPL(debug_object_active_state); > > @@ -999,11 +990,9 @@ EXPORT_SYMBOL_GPL(debug_object_active_state); > > static void __debug_check_no_obj_freed(const void *address, unsigned long size) > > { > > unsigned long flags, oaddr, saddr, eaddr, paddr, chunks; > > - const struct debug_obj_descr *descr; > > - enum debug_obj_state state; > > struct debug_bucket *db; > > struct hlist_node *tmp; > > - struct debug_obj *obj; > > + struct debug_obj *obj, o; > > int cnt, objs_checked = 0; > > saddr = (unsigned long) address; > > @@ -1026,12 +1015,11 @@ static void __debug_check_no_obj_freed(const void *address, unsigned long size) > > switch (obj->state) { > > case ODEBUG_STATE_ACTIVE: > > - descr = obj->descr; > > - state = obj->state; > > + o = *obj; > > raw_spin_unlock_irqrestore(&db->lock, flags); > > - debug_print_object(obj, "free"); > > - debug_object_fixup(descr->fixup_free, > > - (void *) oaddr, state); > > + debug_print_object(&o, "free"); > > + debug_object_fixup(o.descr->fixup_free, > > + (void *) oaddr, o.state); > > goto repeat; > > default: > > hlist_del(&obj->node);