[Devel] [PATCH RHEL7 COMMIT] lists: convert list.h to use READ/WRITE_ONCE
Konstantin Khorenko
khorenko at virtuozzo.com
Thu Nov 2 20:57:54 MSK 2023
The commit is pushed to "branch-rh7-3.10.0-1160.99.1.vz7.211.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1160.99.1.vz7.211.2
------>
commit 894ea4d9527ed7a584635d3887f39fb4aa53a840
Author: Alexander Atanasov <alexander.atanasov at virtuozzo.com>
Date: Thu Sep 28 21:19:49 2023 +0300
lists: convert list.h to use READ/WRITE_ONCE
This is based on different commits from newer kernel versions.
https://jira.vzint.dev/browse/PSBM-150648
Signed-off-by: Alexander Atanasov <alexander.atanasov at virtuozzo.com>
---
include/linux/list.h | 51 +++++++++++++++++++++++++++------------------------
1 file changed, 27 insertions(+), 24 deletions(-)
diff --git a/include/linux/list.h b/include/linux/list.h
index b59d57843f4f..f50c550799d8 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -6,6 +6,7 @@
#include <linux/poison.h>
#include <linux/const.h>
+#include <asm/barrier.h>
/*
* Simple doubly linked list implementation.
*
@@ -23,8 +24,8 @@
static inline void INIT_LIST_HEAD(struct list_head *list)
{
- list->next = list;
- list->prev = list;
+ WRITE_ONCE(list->next, list);
+ WRITE_ONCE(list->prev, list);
}
/*
@@ -41,7 +42,7 @@ static inline void __list_add(struct list_head *new,
next->prev = new;
new->next = next;
new->prev = prev;
- prev->next = new;
+ WRITE_ONCE(prev->next, new);
}
#else
extern void __list_add(struct list_head *new,
@@ -86,7 +87,7 @@ static inline void list_add_tail(struct list_head *new, struct list_head *head)
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
next->prev = prev;
- prev->next = next;
+ WRITE_ONCE(prev->next, next);
}
/**
@@ -208,7 +209,7 @@ static inline int list_is_last(const struct list_head *list,
*/
static inline int list_empty(const struct list_head *head)
{
- return head->next == head;
+ return READ_ONCE(head->next) == head;
}
/**
@@ -227,7 +228,7 @@ static inline int list_empty(const struct list_head *head)
static inline int list_empty_careful(const struct list_head *head)
{
struct list_head *next = head->next;
- return (next == head) && (next == head->prev);
+ return (next == head) && (next == READ_ONCE(head->prev));
}
/**
@@ -403,9 +404,11 @@ static inline void list_splice_tail_init(struct list_head *list,
*
* Note that if the list is empty, it returns NULL.
*/
-#define list_first_entry_or_null(ptr, type, member) \
- (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
-
+#define list_first_entry_or_null(ptr, type, member) ({ \
+ struct list_head *head__ = (ptr); \
+ struct list_head *pos__ = READ_ONCE(head__->next); \
+ pos__ != head__ ? list_entry(pos__, type, member) : NULL; \
+})
/**
* list_next_entry - get the next element in list
* @pos: the type * to cursor
@@ -664,16 +667,16 @@ static inline int hlist_unhashed(const struct hlist_node *h)
static inline int hlist_empty(const struct hlist_head *h)
{
- return !h->first;
+ return !READ_ONCE(h->first);
}
static inline void __hlist_del(struct hlist_node *n)
{
struct hlist_node *next = n->next;
struct hlist_node **pprev = n->pprev;
- *pprev = next;
+ WRITE_ONCE(*pprev, next);
if (next)
- next->pprev = pprev;
+ WRITE_ONCE(next->pprev, pprev);
}
static inline void hlist_del(struct hlist_node *n)
@@ -694,32 +697,32 @@ static inline void hlist_del_init(struct hlist_node *n)
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
struct hlist_node *first = h->first;
- n->next = first;
+ WRITE_ONCE(n->next, first);
if (first)
- first->pprev = &n->next;
- h->first = n;
- n->pprev = &h->first;
+ WRITE_ONCE(first->pprev, &n->next);
+ WRITE_ONCE(h->first, n);
+ WRITE_ONCE(n->pprev, &h->first);
}
/* next must be != NULL */
static inline void hlist_add_before(struct hlist_node *n,
struct hlist_node *next)
{
- n->pprev = next->pprev;
- n->next = next;
- next->pprev = &n->next;
- *(n->pprev) = n;
+ WRITE_ONCE(n->pprev, next->pprev);
+ WRITE_ONCE(n->next, next);
+ WRITE_ONCE(next->pprev, &n->next);
+ WRITE_ONCE(*(n->pprev), n);
}
static inline void hlist_add_behind(struct hlist_node *n,
struct hlist_node *prev)
{
- n->next = prev->next;
- prev->next = n;
- n->pprev = &prev->next;
+ WRITE_ONCE(n->next, prev->next);
+ WRITE_ONCE(prev->next, n);
+ WRITE_ONCE(n->pprev, &prev->next);
if (n->next)
- n->next->pprev = &n->next;
+ WRITE_ONCE(n->next->pprev, &n->next);
}
/* after that we'll appear to be on some hlist and hlist_del will work */
More information about the Devel
mailing list