* [PATCH 07/13] drivers/edac: convert pci counters to seqnum_ops
2020-11-10 19:53 [PATCH 00/13] Introduce seqnum_ops Shuah Khan
@ 2020-11-10 19:53 ` Shuah Khan
2020-11-10 20:44 ` [PATCH 00/13] Introduce seqnum_ops Alan Stern
2020-11-11 4:33 ` Matthew Wilcox
2 siblings, 0 replies; 7+ messages in thread
From: Shuah Khan @ 2020-11-10 19:53 UTC (permalink / raw)
To: bp, mchehab, tony.luck, james.morse, rric, gregkh, keescook, peterz
Cc: Shuah Khan, linux-edac, linux-kernel
seqnum_ops api is introduced to be used when a variable is used as
a sequence/stat counter and doesn't guard object lifetimes. This
clearly differentiates atomic_t usages that guard object lifetimes.
seqnum32 variables wrap around to INT_MIN when it overflows and
should not be used to guard resource lifetimes, device usage and
open counts that control state changes, and pm states.
atomic_t variables used for pci counters keep track of pci parity and
non-parity errors. Convert them to use seqnum_ops.
Overflow will wrap around and reset the counts as was the case prior to
the conversion.
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
---
drivers/edac/edac_pci.h | 5 +++--
drivers/edac/edac_pci_sysfs.c | 28 ++++++++++++++--------------
2 files changed, 17 insertions(+), 16 deletions(-)
diff --git a/drivers/edac/edac_pci.h b/drivers/edac/edac_pci.h
index 5175f5724cfa..33b33e62c37f 100644
--- a/drivers/edac/edac_pci.h
+++ b/drivers/edac/edac_pci.h
@@ -30,12 +30,13 @@
#include <linux/pci.h>
#include <linux/types.h>
#include <linux/workqueue.h>
+#include <linux/seqnum_ops.h>
#ifdef CONFIG_PCI
struct edac_pci_counter {
- atomic_t pe_count;
- atomic_t npe_count;
+ struct seqnum32 pe_count;
+ struct seqnum32 npe_count;
};
/*
diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c
index 53042af7262e..96f950fb39b0 100644
--- a/drivers/edac/edac_pci_sysfs.c
+++ b/drivers/edac/edac_pci_sysfs.c
@@ -23,8 +23,8 @@ static int edac_pci_log_pe = 1; /* log PCI parity errors */
static int edac_pci_log_npe = 1; /* log PCI non-parity error errors */
static int edac_pci_poll_msec = 1000; /* one second workq period */
-static atomic_t pci_parity_count = ATOMIC_INIT(0);
-static atomic_t pci_nonparity_count = ATOMIC_INIT(0);
+static struct seqnum32 pci_parity_count = SEQNUM_INIT(0);
+static struct seqnum32 pci_nonparity_count = SEQNUM_INIT(0);
static struct kobject *edac_pci_top_main_kobj;
static atomic_t edac_pci_sysfs_refcount = ATOMIC_INIT(0);
@@ -58,13 +58,13 @@ int edac_pci_get_poll_msec(void)
/**************************** EDAC PCI sysfs instance *******************/
static ssize_t instance_pe_count_show(struct edac_pci_ctl_info *pci, char *data)
{
- return sprintf(data, "%u\n", atomic_read(&pci->counters.pe_count));
+ return sprintf(data, "%u\n", seqnum32_read(&pci->counters.pe_count));
}
static ssize_t instance_npe_count_show(struct edac_pci_ctl_info *pci,
char *data)
{
- return sprintf(data, "%u\n", atomic_read(&pci->counters.npe_count));
+ return sprintf(data, "%u\n", seqnum32_read(&pci->counters.npe_count));
}
#define to_instance(k) container_of(k, struct edac_pci_ctl_info, kobj)
@@ -553,7 +553,7 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev)
edac_printk(KERN_CRIT, EDAC_PCI,
"Signaled System Error on %s\n",
pci_name(dev));
- atomic_inc(&pci_nonparity_count);
+ seqnum32_inc(&pci_nonparity_count);
}
if (status & (PCI_STATUS_PARITY)) {
@@ -561,7 +561,7 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev)
"Master Data Parity Error on %s\n",
pci_name(dev));
- atomic_inc(&pci_parity_count);
+ seqnum32_inc(&pci_parity_count);
}
if (status & (PCI_STATUS_DETECTED_PARITY)) {
@@ -569,7 +569,7 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev)
"Detected Parity Error on %s\n",
pci_name(dev));
- atomic_inc(&pci_parity_count);
+ seqnum32_inc(&pci_parity_count);
}
}
@@ -592,7 +592,7 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev)
edac_printk(KERN_CRIT, EDAC_PCI, "Bridge "
"Signaled System Error on %s\n",
pci_name(dev));
- atomic_inc(&pci_nonparity_count);
+ seqnum32_inc(&pci_nonparity_count);
}
if (status & (PCI_STATUS_PARITY)) {
@@ -600,7 +600,7 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev)
"Master Data Parity Error on "
"%s\n", pci_name(dev));
- atomic_inc(&pci_parity_count);
+ seqnum32_inc(&pci_parity_count);
}
if (status & (PCI_STATUS_DETECTED_PARITY)) {
@@ -608,7 +608,7 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev)
"Detected Parity Error on %s\n",
pci_name(dev));
- atomic_inc(&pci_parity_count);
+ seqnum32_inc(&pci_parity_count);
}
}
}
@@ -646,7 +646,7 @@ void edac_pci_do_parity_check(void)
if (!check_pci_errors)
return;
- before_count = atomic_read(&pci_parity_count);
+ before_count = seqnum32_read(&pci_parity_count);
/* scan all PCI devices looking for a Parity Error on devices and
* bridges.
@@ -658,7 +658,7 @@ void edac_pci_do_parity_check(void)
/* Only if operator has selected panic on PCI Error */
if (edac_pci_get_panic_on_pe()) {
/* If the count is different 'after' from 'before' */
- if (before_count != atomic_read(&pci_parity_count))
+ if (before_count != seqnum32_read(&pci_parity_count))
panic("EDAC: PCI Parity Error");
}
}
@@ -686,7 +686,7 @@ void edac_pci_handle_pe(struct edac_pci_ctl_info *pci, const char *msg)
{
/* global PE counter incremented by edac_pci_do_parity_check() */
- atomic_inc(&pci->counters.pe_count);
+ seqnum32_inc(&pci->counters.pe_count);
if (edac_pci_get_log_pe())
edac_pci_printk(pci, KERN_WARNING,
@@ -711,7 +711,7 @@ void edac_pci_handle_npe(struct edac_pci_ctl_info *pci, const char *msg)
{
/* global NPE counter incremented by edac_pci_do_parity_check() */
- atomic_inc(&pci->counters.npe_count);
+ seqnum32_inc(&pci->counters.npe_count);
if (edac_pci_get_log_npe())
edac_pci_printk(pci, KERN_WARNING,
--
2.27.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 00/13] Introduce seqnum_ops
2020-11-10 19:53 [PATCH 00/13] Introduce seqnum_ops Shuah Khan
2020-11-10 19:53 ` [PATCH 07/13] drivers/edac: convert pci counters to seqnum_ops Shuah Khan
@ 2020-11-10 20:44 ` Alan Stern
2020-11-10 22:42 ` Shuah Khan
2020-11-11 4:33 ` Matthew Wilcox
2 siblings, 1 reply; 7+ messages in thread
From: Alan Stern @ 2020-11-10 20:44 UTC (permalink / raw)
To: Shuah Khan
Cc: corbet, keescook, gregkh, peterz, rafael, lenb, james.morse,
tony.luck, bp, minyard, arnd, mchehab, rric, valentina.manea.m,
shuah, zohar, dmitry.kasatkin, jmorris, serge, linux-doc,
linux-kernel, linux-kselftest, linux-acpi, openipmi-developer,
linux-edac, linux-usb, linux-integrity, linux-security-module
On Tue, Nov 10, 2020 at 12:53:26PM -0700, Shuah Khan wrote:
> There are a number of atomic_t usages in the kernel where atomic_t api
> is used strictly for counting sequence numbers and other statistical
> counters and not for managing object lifetime.
>
> The purpose of these Sequence Number Ops is to clearly differentiate
> atomic_t counter usages from atomic_t usages that guard object lifetimes,
> hence prone to overflow and underflow errors.
>
> The atomic_t api provides a wide range of atomic operations as a base
> api to implement atomic counters, bitops, spinlock interfaces. The usages
> also evolved into being used for resource lifetimes and state management.
> The refcount_t api was introduced to address resource lifetime problems
> related to atomic_t wrapping. There is a large overlap between the
> atomic_t api used for resource lifetimes and just counters, stats, and
> sequence numbers. It has become difficult to differentiate between the
> atomic_t usages that should be converted to refcount_t and the ones that
> can be left alone. Introducing seqnum_ops to wrap the usages that are
> stats, counters, sequence numbers makes it easier for tools that scan
> for underflow and overflow on atomic_t usages to detect overflow and
> underflows to scan just the cases that are prone to errors.
>
> Sequence Number api provides interfaces for simple atomic_t counter usages
> that just count, and don't guard resource lifetimes. The seqnum_ops are
> built on top of atomic_t api, providing a smaller subset of atomic_t
> interfaces necessary to support atomic_t usages as simple counters.
> This api has init/set/inc/dec/read and doesn't support any other atomic_t
> ops with the intent to restrict the use of these interfaces as simple
> counting usages.
>
> Sequence Numbers wrap around to INT_MIN when it overflows and should not
> be used to guard resource lifetimes, device usage and open counts that
> control state changes, and pm states. Overflowing to INT_MIN is consistent
> with the atomic_t api, which it is built on top of.
If Sequence Numbers are subject to wraparound then they aren't reliable.
Given that they aren't reliable, why use atomic instructions at all?
Why not just use plain regular integers with READ_ONCE and WRITE_ONCE?
Alan Stern
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 00/13] Introduce seqnum_ops
2020-11-10 20:44 ` [PATCH 00/13] Introduce seqnum_ops Alan Stern
@ 2020-11-10 22:42 ` Shuah Khan
0 siblings, 0 replies; 7+ messages in thread
From: Shuah Khan @ 2020-11-10 22:42 UTC (permalink / raw)
To: Alan Stern
Cc: corbet, keescook, gregkh, peterz, rafael, lenb, james.morse,
tony.luck, bp, minyard, arnd, mchehab, rric, valentina.manea.m,
shuah, zohar, dmitry.kasatkin, jmorris, serge, linux-doc,
linux-kernel, linux-kselftest, linux-acpi, openipmi-developer,
linux-edac, linux-usb, linux-integrity, linux-security-module
On 11/10/20 1:44 PM, Alan Stern wrote:
> On Tue, Nov 10, 2020 at 12:53:26PM -0700, Shuah Khan wrote:
>> There are a number of atomic_t usages in the kernel where atomic_t api
>> is used strictly for counting sequence numbers and other statistical
>> counters and not for managing object lifetime.
>>
>> The purpose of these Sequence Number Ops is to clearly differentiate
>> atomic_t counter usages from atomic_t usages that guard object lifetimes,
>> hence prone to overflow and underflow errors.
>>
>> The atomic_t api provides a wide range of atomic operations as a base
>> api to implement atomic counters, bitops, spinlock interfaces. The usages
>> also evolved into being used for resource lifetimes and state management.
>> The refcount_t api was introduced to address resource lifetime problems
>> related to atomic_t wrapping. There is a large overlap between the
>> atomic_t api used for resource lifetimes and just counters, stats, and
>> sequence numbers. It has become difficult to differentiate between the
>> atomic_t usages that should be converted to refcount_t and the ones that
>> can be left alone. Introducing seqnum_ops to wrap the usages that are
>> stats, counters, sequence numbers makes it easier for tools that scan
>> for underflow and overflow on atomic_t usages to detect overflow and
>> underflows to scan just the cases that are prone to errors.
>>
>> Sequence Number api provides interfaces for simple atomic_t counter usages
>> that just count, and don't guard resource lifetimes. The seqnum_ops are
>> built on top of atomic_t api, providing a smaller subset of atomic_t
>> interfaces necessary to support atomic_t usages as simple counters.
>> This api has init/set/inc/dec/read and doesn't support any other atomic_t
>> ops with the intent to restrict the use of these interfaces as simple
>> counting usages.
>>
>> Sequence Numbers wrap around to INT_MIN when it overflows and should not
>> be used to guard resource lifetimes, device usage and open counts that
>> control state changes, and pm states. Overflowing to INT_MIN is consistent
>> with the atomic_t api, which it is built on top of.
>
> If Sequence Numbers are subject to wraparound then they aren't reliable.
> Given that they aren't reliable, why use atomic instructions at all?
> Why not just use plain regular integers with READ_ONCE and WRITE_ONCE?
>
You still need atomic update for these numbers. The intent is to provide
atomic api for cases where the variable doesn't guard lifetimes and yet
needs atomic instructions.
Several such usages where atomic_t is used for up counting, also use
upper bounds. It is also an option to switch to seqnum64 to avoid
wrap around in case there is a concern.
thanks,
-- Shuah
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 00/13] Introduce seqnum_ops
2020-11-10 19:53 [PATCH 00/13] Introduce seqnum_ops Shuah Khan
2020-11-10 19:53 ` [PATCH 07/13] drivers/edac: convert pci counters to seqnum_ops Shuah Khan
2020-11-10 20:44 ` [PATCH 00/13] Introduce seqnum_ops Alan Stern
@ 2020-11-11 4:33 ` Matthew Wilcox
2020-11-11 16:03 ` Shuah Khan
2 siblings, 1 reply; 7+ messages in thread
From: Matthew Wilcox @ 2020-11-11 4:33 UTC (permalink / raw)
To: Shuah Khan
Cc: corbet, keescook, gregkh, peterz, rafael, lenb, james.morse,
tony.luck, bp, minyard, arnd, mchehab, rric, valentina.manea.m,
shuah, zohar, dmitry.kasatkin, jmorris, serge, linux-doc,
linux-kernel, linux-kselftest, linux-acpi, openipmi-developer,
linux-edac, linux-usb, linux-integrity, linux-security-module
On Tue, Nov 10, 2020 at 12:53:26PM -0700, Shuah Khan wrote:
> There are a number of atomic_t usages in the kernel where atomic_t api
> is used strictly for counting sequence numbers and other statistical
> counters and not for managing object lifetime.
We already have something in Linux called a sequence counter, and it's
different from this. ID counter? instance number? monotonic_t? stat_t?
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 00/13] Introduce seqnum_ops
2020-11-11 4:33 ` Matthew Wilcox
@ 2020-11-11 16:03 ` Shuah Khan
2020-11-11 16:41 ` Matthew Wilcox
0 siblings, 1 reply; 7+ messages in thread
From: Shuah Khan @ 2020-11-11 16:03 UTC (permalink / raw)
To: Matthew Wilcox
Cc: corbet, keescook, gregkh, peterz, rafael, lenb, james.morse,
tony.luck, bp, minyard, arnd, mchehab, rric, valentina.manea.m,
shuah, zohar, dmitry.kasatkin, jmorris, serge, linux-doc,
linux-kernel, linux-kselftest, linux-acpi, openipmi-developer,
linux-edac, linux-usb, linux-integrity, linux-security-module,
skhan
On 11/10/20 9:33 PM, Matthew Wilcox wrote:
> On Tue, Nov 10, 2020 at 12:53:26PM -0700, Shuah Khan wrote:
>> There are a number of atomic_t usages in the kernel where atomic_t api
>> is used strictly for counting sequence numbers and other statistical
>> counters and not for managing object lifetime.
>
> We already have something in Linux called a sequence counter, and it's
> different from this. ID counter? instance number? monotonic_t? stat_t?
>
No results for monotonic_t or stat_t. Can you give me a pointer to what
your referring to.
thanks,
-- Shuah
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 00/13] Introduce seqnum_ops
2020-11-11 16:03 ` Shuah Khan
@ 2020-11-11 16:41 ` Matthew Wilcox
0 siblings, 0 replies; 7+ messages in thread
From: Matthew Wilcox @ 2020-11-11 16:41 UTC (permalink / raw)
To: Shuah Khan
Cc: corbet, keescook, gregkh, peterz, rafael, lenb, james.morse,
tony.luck, bp, minyard, arnd, mchehab, rric, valentina.manea.m,
shuah, zohar, dmitry.kasatkin, jmorris, serge, linux-doc,
linux-kernel, linux-kselftest, linux-acpi, openipmi-developer,
linux-edac, linux-usb, linux-integrity, linux-security-module
On Wed, Nov 11, 2020 at 09:03:20AM -0700, Shuah Khan wrote:
> On 11/10/20 9:33 PM, Matthew Wilcox wrote:
> > On Tue, Nov 10, 2020 at 12:53:26PM -0700, Shuah Khan wrote:
> > > There are a number of atomic_t usages in the kernel where atomic_t api
> > > is used strictly for counting sequence numbers and other statistical
> > > counters and not for managing object lifetime.
> >
> > We already have something in Linux called a sequence counter, and it's
> > different from this. ID counter? instance number? monotonic_t? stat_t?
> >
>
> No results for monotonic_t or stat_t. Can you give me a pointer to what
> your referring to.
We have a seqcount_t. We need to call this something different.
maybe we should call it stat_t (and for that usage, stat_add() as well
as stat_inc() is a legitimate API to have).
^ permalink raw reply [flat|nested] 7+ messages in thread