perf-eh_elf/util/rb_resort.h

152 lines
4.9 KiB
C
Raw Normal View History

Merge tag 'afs-fixes-20180514' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs Pull AFS fixes from David Howells: "Here's a set of patches that fix a number of bugs in the in-kernel AFS client, including: - Fix directory locking to not use individual page locks for directory reading/scanning but rather to use a semaphore on the afs_vnode struct as the directory contents must be read in a single blob and data from different reads must not be mixed as the entire contents may be shuffled about between reads. - Fix address list parsing to handle port specifiers correctly. - Only give up callback records on a server if we actually talked to that server (we might not be able to access a server). - Fix some callback handling bugs, including refcounting, whole-volume callbacks and when callbacks actually get broken in response to a CB.CallBack op. - Fix some server/address rotation bugs, including giving up if we can't probe a server; giving up if a server says it doesn't have a volume, but there are more servers to try. - Fix the decoding of fetched statuses to be OpenAFS compatible. - Fix the handling of server lookups in Cache Manager ops (such as CB.InitCallBackState3) to use a UUID if possible and to handle no server being found. - Fix a bug in server lookup where not all addresses are compared. - Fix the non-encryption of calls that prevents some servers from being accessed (this also requires an AF_RXRPC patch that has already gone in through the net tree). There's also a patch that adds tracepoints to log Cache Manager ops that don't find a matching server, either by UUID or by address" * tag 'afs-fixes-20180514' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs: afs: Fix the non-encryption of calls afs: Fix CB.CallBack handling afs: Fix whole-volume callback handling afs: Fix afs_find_server search loop afs: Fix the handling of an unfound server in CM operations afs: Add a tracepoint to record callbacks from unlisted servers afs: Fix the handling of CB.InitCallBackState3 to find the server by UUID afs: Fix VNOVOL handling in address rotation afs: Fix AFSFetchStatus decoder to provide OpenAFS compatibility afs: Fix server rotation's handling of fileserver probe failure afs: Fix refcounting in callback registration afs: Fix giving up callbacks on server destruction afs: Fix address list parsing afs: Fix directory page locking
2018-05-15 19:48:36 +02:00
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PERF_RESORT_RB_H_
#define _PERF_RESORT_RB_H_
/*
* Template for creating a class to resort an existing rb_tree according to
* a new sort criteria, that must be present in the entries of the source
* rb_tree.
*
* (c) 2016 Arnaldo Carvalho de Melo <acme@redhat.com>
*
* Quick example, resorting threads by its shortname:
*
* First define the prefix (threads) to be used for the functions and data
* structures created, and provide an expression for the sorting, then the
* fields to be present in each of the entries in the new, sorted, rb_tree.
*
* The body of the init function should collect the fields, maybe
* pre-calculating them from multiple entries in the original 'entry' from
* the rb_tree used as a source for the entries to be sorted:
DEFINE_RB_RESORT_RB(threads, strcmp(a->thread->shortname,
b->thread->shortname) < 0,
struct thread *thread;
)
{
entry->thread = rb_entry(nd, struct thread, rb_node);
}
* After this it is just a matter of instantiating it and iterating it,
* for a few data structures with existing rb_trees, such as 'struct machine',
* helpers are available to get the rb_root and the nr_entries:
DECLARE_RESORT_RB_MACHINE_THREADS(threads, machine_ptr);
* This will instantiate the new rb_tree and a cursor for it, that can be used as:
struct rb_node *nd;
resort_rb__for_each_entry(nd, threads) {
struct thread *t = threads_entry;
printf("%s: %d\n", t->shortname, t->tid);
}
* Then delete it:
resort_rb__delete(threads);
* The name of the data structures and functions will have a _sorted suffix
* right before the method names, i.e. will look like:
*
* struct threads_sorted_entry {}
* threads_sorted__insert()
*/
#define DEFINE_RESORT_RB(__name, __comp, ...) \
struct __name##_sorted_entry { \
struct rb_node rb_node; \
__VA_ARGS__ \
}; \
static void __name##_sorted__init_entry(struct rb_node *nd, \
struct __name##_sorted_entry *entry); \
\
static int __name##_sorted__cmp(struct rb_node *nda, struct rb_node *ndb) \
{ \
struct __name##_sorted_entry *a, *b; \
a = rb_entry(nda, struct __name##_sorted_entry, rb_node); \
b = rb_entry(ndb, struct __name##_sorted_entry, rb_node); \
return __comp; \
} \
\
struct __name##_sorted { \
struct rb_root entries; \
struct __name##_sorted_entry nd[0]; \
}; \
\
static void __name##_sorted__insert(struct __name##_sorted *sorted, \
struct rb_node *sorted_nd) \
{ \
struct rb_node **p = &sorted->entries.rb_node, *parent = NULL; \
while (*p != NULL) { \
parent = *p; \
if (__name##_sorted__cmp(sorted_nd, parent)) \
p = &(*p)->rb_left; \
else \
p = &(*p)->rb_right; \
} \
rb_link_node(sorted_nd, parent, p); \
rb_insert_color(sorted_nd, &sorted->entries); \
} \
\
static void __name##_sorted__sort(struct __name##_sorted *sorted, \
struct rb_root *entries) \
{ \
struct rb_node *nd; \
unsigned int i = 0; \
for (nd = rb_first(entries); nd; nd = rb_next(nd)) { \
struct __name##_sorted_entry *snd = &sorted->nd[i++]; \
__name##_sorted__init_entry(nd, snd); \
__name##_sorted__insert(sorted, &snd->rb_node); \
} \
} \
\
static struct __name##_sorted *__name##_sorted__new(struct rb_root *entries, \
int nr_entries) \
{ \
struct __name##_sorted *sorted; \
sorted = malloc(sizeof(*sorted) + sizeof(sorted->nd[0]) * nr_entries); \
if (sorted) { \
sorted->entries = RB_ROOT; \
__name##_sorted__sort(sorted, entries); \
} \
return sorted; \
} \
\
static void __name##_sorted__delete(struct __name##_sorted *sorted) \
{ \
free(sorted); \
} \
\
static void __name##_sorted__init_entry(struct rb_node *nd, \
struct __name##_sorted_entry *entry)
#define DECLARE_RESORT_RB(__name) \
struct __name##_sorted_entry *__name##_entry; \
struct __name##_sorted *__name = __name##_sorted__new
#define resort_rb__for_each_entry(__nd, __name) \
for (__nd = rb_first(&__name->entries); \
__name##_entry = rb_entry(__nd, struct __name##_sorted_entry, \
rb_node), __nd; \
__nd = rb_next(__nd))
#define resort_rb__delete(__name) \
__name##_sorted__delete(__name), __name = NULL
/*
* Helpers for other classes that contains both an rbtree and the
* number of entries in it:
*/
/* For 'struct intlist' */
#define DECLARE_RESORT_RB_INTLIST(__name, __ilist) \
DECLARE_RESORT_RB(__name)(&__ilist->rblist.entries, \
__ilist->rblist.nr_entries)
/* For 'struct machine->threads' */
#define DECLARE_RESORT_RB_MACHINE_THREADS(__name, __machine, hash_bucket) \
DECLARE_RESORT_RB(__name)(&__machine->threads[hash_bucket].entries, \
__machine->threads[hash_bucket].nr)
#endif /* _PERF_RESORT_RB_H_ */