Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

list_lru: expand list_lru_add() docs with info about sublists

The documentation for list_lru_add() and list_lru_del() has not been
updated since lru lists were originally introduced by commit a38e40824844
("list: add a new LRU list type"). Back then, list_lru stored all of the
items in a single list, but the implementation has since been expanded to
use many sublists internally.

Thus, update the docs to mention that the requirements about not using the
item with several lists at the same time also applies not using different
sublists. Also mention that list_lru items are reparented when the memcg
is deleted as discussed on the LKML [1].

Also fix incorrect use of 'Return value:' which should be 'Return:'.

Link: https://lore.kernel.org/all/Z0eXrllVhRI9Ag5b@dread.disaster.area/ [1]
Link: https://lkml.kernel.org/r/20241129-list_lru_memcg_docs-v2-1-e285ff1c481b@google.com
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Acked-by: Muchun Song <muchun.song@linux.dev>
Reviewed-by: Nhat Pham <nphamcs@gmail.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Qi Zheng <zhengqi.arch@bytedance.com>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Alice Ryhl and committed by
Andrew Morton
da80f4ff 58d534c8

+33 -11
+33 -11
include/linux/list_lru.h
··· 91 91 * @memcg: the cgroup of the sublist to add the item to. 92 92 * 93 93 * If the element is already part of a list, this function returns doing 94 - * nothing. Therefore the caller does not need to keep state about whether or 95 - * not the element already belongs in the list and is allowed to lazy update 96 - * it. Note however that this is valid for *a* list, not *this* list. If 97 - * the caller organize itself in a way that elements can be in more than 98 - * one type of list, it is up to the caller to fully remove the item from 99 - * the previous list (with list_lru_del() for instance) before moving it 100 - * to @lru. 94 + * nothing. This means that it is not necessary to keep state about whether or 95 + * not the element already belongs in the list. That said, this logic only 96 + * works if the item is in *this* list. If the item might be in some other 97 + * list, then you cannot rely on this check and you must remove it from the 98 + * other list before trying to insert it. 99 + * 100 + * The lru list consists of many sublists internally; the @nid and @memcg 101 + * parameters are used to determine which sublist to insert the item into. 102 + * It's important to use the right value of @nid and @memcg when deleting the 103 + * item, since it might otherwise get deleted from the wrong sublist. 104 + * 105 + * This also applies when attempting to insert the item multiple times - if 106 + * the item is currently in one sublist and you call list_lru_add() again, you 107 + * must pass the right @nid and @memcg parameters so that the same sublist is 108 + * used. 109 + * 110 + * You must ensure that the memcg is not freed during this call (e.g., with 111 + * rcu or by taking a css refcnt). 101 112 * 102 113 * Return: true if the list was updated, false otherwise 103 114 */ ··· 124 113 * memcg of the sublist is determined by @item list_head. This assumption is 125 114 * valid for slab objects LRU such as dentries, inodes, etc. 126 115 * 127 - * Return value: true if the list was updated, false otherwise 116 + * Return: true if the list was updated, false otherwise 128 117 */ 129 118 bool list_lru_add_obj(struct list_lru *lru, struct list_head *item); 130 119 ··· 136 125 * @memcg: the cgroup of the sublist to delete the item from. 137 126 * 138 127 * This function works analogously as list_lru_add() in terms of list 139 - * manipulation. The comments about an element already pertaining to 140 - * a list are also valid for list_lru_del(). 128 + * manipulation. 129 + * 130 + * The comments in list_lru_add() about an element already being in a list are 131 + * also valid for list_lru_del(), that is, you can delete an item that has 132 + * already been removed or never been added. However, if the item is in a 133 + * list, it must be in *this* list, and you must pass the right value of @nid 134 + * and @memcg so that the right sublist is used. 135 + * 136 + * You must ensure that the memcg is not freed during this call (e.g., with 137 + * rcu or by taking a css refcnt). When a memcg is deleted, list_lru entries 138 + * are automatically moved to the parent memcg. This is done in a race-free 139 + * way, so during deletion of an memcg both the old and new memcg will resolve 140 + * to the same sublist internally. 141 141 * 142 142 * Return: true if the list was updated, false otherwise 143 143 */ ··· 164 142 * memcg of the sublist is determined by @item list_head. This assumption is 165 143 * valid for slab objects LRU such as dentries, inodes, etc. 166 144 * 167 - * Return value: true if the list was updated, false otherwise. 145 + * Return: true if the list was updated, false otherwise. 168 146 */ 169 147 bool list_lru_del_obj(struct list_lru *lru, struct list_head *item); 170 148