diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/lib/bpf/README.rst | 168 | ||||
-rw-r--r-- | tools/lib/bpf/libbpf.c | 4 | ||||
-rw-r--r-- | tools/lib/bpf/netlink.c | 115 | ||||
-rw-r--r-- | tools/lib/bpf/nlattr.c | 2 | ||||
-rw-r--r-- | tools/lib/bpf/nlattr.h | 38 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/prog_tests/ringbuf.c | 2 |
6 files changed, 74 insertions, 255 deletions
diff --git a/tools/lib/bpf/README.rst b/tools/lib/bpf/README.rst deleted file mode 100644 index 8928f7787f2d..000000000000 --- a/tools/lib/bpf/README.rst +++ /dev/null @@ -1,168 +0,0 @@ -.. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) - -libbpf API naming convention -============================ - -libbpf API provides access to a few logically separated groups of -functions and types. Every group has its own naming convention -described here. It's recommended to follow these conventions whenever a -new function or type is added to keep libbpf API clean and consistent. - -All types and functions provided by libbpf API should have one of the -following prefixes: ``bpf_``, ``btf_``, ``libbpf_``, ``xsk_``, -``perf_buffer_``. - -System call wrappers --------------------- - -System call wrappers are simple wrappers for commands supported by -sys_bpf system call. These wrappers should go to ``bpf.h`` header file -and map one-on-one to corresponding commands. - -For example ``bpf_map_lookup_elem`` wraps ``BPF_MAP_LOOKUP_ELEM`` -command of sys_bpf, ``bpf_prog_attach`` wraps ``BPF_PROG_ATTACH``, etc. - -Objects -------- - -Another class of types and functions provided by libbpf API is "objects" -and functions to work with them. Objects are high-level abstractions -such as BPF program or BPF map. They're represented by corresponding -structures such as ``struct bpf_object``, ``struct bpf_program``, -``struct bpf_map``, etc. - -Structures are forward declared and access to their fields should be -provided via corresponding getters and setters rather than directly. - -These objects are associated with corresponding parts of ELF object that -contains compiled BPF programs. - -For example ``struct bpf_object`` represents ELF object itself created -from an ELF file or from a buffer, ``struct bpf_program`` represents a -program in ELF object and ``struct bpf_map`` is a map. - -Functions that work with an object have names built from object name, -double underscore and part that describes function purpose. - -For example ``bpf_object__open`` consists of the name of corresponding -object, ``bpf_object``, double underscore and ``open`` that defines the -purpose of the function to open ELF file and create ``bpf_object`` from -it. - -Another example: ``bpf_program__load`` is named for corresponding -object, ``bpf_program``, that is separated from other part of the name -by double underscore. - -All objects and corresponding functions other than BTF related should go -to ``libbpf.h``. BTF types and functions should go to ``btf.h``. - -Auxiliary functions -------------------- - -Auxiliary functions and types that don't fit well in any of categories -described above should have ``libbpf_`` prefix, e.g. -``libbpf_get_error`` or ``libbpf_prog_type_by_name``. - -AF_XDP functions -------------------- - -AF_XDP functions should have an ``xsk_`` prefix, e.g. -``xsk_umem__get_data`` or ``xsk_umem__create``. The interface consists -of both low-level ring access functions and high-level configuration -functions. These can be mixed and matched. Note that these functions -are not reentrant for performance reasons. - -Please take a look at Documentation/networking/af_xdp.rst in the Linux -kernel source tree on how to use XDP sockets and for some common -mistakes in case you do not get any traffic up to user space. - -libbpf ABI -========== - -libbpf can be both linked statically or used as DSO. To avoid possible -conflicts with other libraries an application is linked with, all -non-static libbpf symbols should have one of the prefixes mentioned in -API documentation above. See API naming convention to choose the right -name for a new symbol. - -Symbol visibility ------------------ - -libbpf follow the model when all global symbols have visibility "hidden" -by default and to make a symbol visible it has to be explicitly -attributed with ``LIBBPF_API`` macro. For example: - -.. code-block:: c - - LIBBPF_API int bpf_prog_get_fd_by_id(__u32 id); - -This prevents from accidentally exporting a symbol, that is not supposed -to be a part of ABI what, in turn, improves both libbpf developer- and -user-experiences. - -ABI versionning ---------------- - -To make future ABI extensions possible libbpf ABI is versioned. -Versioning is implemented by ``libbpf.map`` version script that is -passed to linker. - -Version name is ``LIBBPF_`` prefix + three-component numeric version, -starting from ``0.0.1``. - -Every time ABI is being changed, e.g. because a new symbol is added or -semantic of existing symbol is changed, ABI version should be bumped. -This bump in ABI version is at most once per kernel development cycle. - -For example, if current state of ``libbpf.map`` is: - -.. code-block:: - LIBBPF_0.0.1 { - global: - bpf_func_a; - bpf_func_b; - local: - \*; - }; - -, and a new symbol ``bpf_func_c`` is being introduced, then -``libbpf.map`` should be changed like this: - -.. code-block:: - LIBBPF_0.0.1 { - global: - bpf_func_a; - bpf_func_b; - local: - \*; - }; - LIBBPF_0.0.2 { - global: - bpf_func_c; - } LIBBPF_0.0.1; - -, where new version ``LIBBPF_0.0.2`` depends on the previous -``LIBBPF_0.0.1``. - -Format of version script and ways to handle ABI changes, including -incompatible ones, described in details in [1]. - -Stand-alone build -================= - -Under https://github.com/libbpf/libbpf there is a (semi-)automated -mirror of the mainline's version of libbpf for a stand-alone build. - -However, all changes to libbpf's code base must be upstreamed through -the mainline kernel tree. - -License -======= - -libbpf is dual-licensed under LGPL 2.1 and BSD 2-Clause. - -Links -===== - -[1] https://www.akkadia.org/drepper/dsohowto.pdf - (Chapter 3. Maintaining APIs and ABIs). diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 48c0ade05ab1..1e04ce724240 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -4001,6 +4001,10 @@ bpf_object__probe_loading(struct bpf_object *obj) ret = bpf_load_program_xattr(&attr, NULL, 0); if (ret < 0) { + attr.prog_type = BPF_PROG_TYPE_TRACEPOINT; + ret = bpf_load_program_xattr(&attr, NULL, 0); + } + if (ret < 0) { ret = errno; cp = libbpf_strerror_r(ret, errmsg, sizeof(errmsg)); pr_warn("Error in %s():%s(%d). Couldn't load trivial BPF " diff --git a/tools/lib/bpf/netlink.c b/tools/lib/bpf/netlink.c index cf9381f03b16..39f25e09b51e 100644 --- a/tools/lib/bpf/netlink.c +++ b/tools/lib/bpf/netlink.c @@ -154,7 +154,7 @@ done: return ret; } -static int libbpf_netlink_send_recv(struct nlmsghdr *nh, +static int libbpf_netlink_send_recv(struct libbpf_nla_req *req, __dump_nlmsg_t parse_msg, libbpf_dump_nlmsg_t parse_attr, void *cookie) @@ -166,15 +166,15 @@ static int libbpf_netlink_send_recv(struct nlmsghdr *nh, if (sock < 0) return sock; - nh->nlmsg_pid = 0; - nh->nlmsg_seq = time(NULL); + req->nh.nlmsg_pid = 0; + req->nh.nlmsg_seq = time(NULL); - if (send(sock, nh, nh->nlmsg_len, 0) < 0) { + if (send(sock, req, req->nh.nlmsg_len, 0) < 0) { ret = -errno; goto out; } - ret = libbpf_netlink_recv(sock, nl_pid, nh->nlmsg_seq, + ret = libbpf_netlink_recv(sock, nl_pid, req->nh.nlmsg_seq, parse_msg, parse_attr, cookie); out: libbpf_netlink_close(sock); @@ -186,11 +186,7 @@ static int __bpf_set_link_xdp_fd_replace(int ifindex, int fd, int old_fd, { struct nlattr *nla; int ret; - struct { - struct nlmsghdr nh; - struct ifinfomsg ifinfo; - char attrbuf[64]; - } req; + struct libbpf_nla_req req; memset(&req, 0, sizeof(req)); req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); @@ -199,27 +195,26 @@ static int __bpf_set_link_xdp_fd_replace(int ifindex, int fd, int old_fd, req.ifinfo.ifi_family = AF_UNSPEC; req.ifinfo.ifi_index = ifindex; - nla = nlattr_begin_nested(&req.nh, sizeof(req), IFLA_XDP); + nla = nlattr_begin_nested(&req, IFLA_XDP); if (!nla) return -EMSGSIZE; - ret = nlattr_add(&req.nh, sizeof(req), IFLA_XDP_FD, &fd, sizeof(fd)); + ret = nlattr_add(&req, IFLA_XDP_FD, &fd, sizeof(fd)); if (ret < 0) return ret; if (flags) { - ret = nlattr_add(&req.nh, sizeof(req), IFLA_XDP_FLAGS, &flags, - sizeof(flags)); + ret = nlattr_add(&req, IFLA_XDP_FLAGS, &flags, sizeof(flags)); if (ret < 0) return ret; } if (flags & XDP_FLAGS_REPLACE) { - ret = nlattr_add(&req.nh, sizeof(req), IFLA_XDP_EXPECTED_FD, - &old_fd, sizeof(old_fd)); + ret = nlattr_add(&req, IFLA_XDP_EXPECTED_FD, &old_fd, + sizeof(old_fd)); if (ret < 0) return ret; } - nlattr_end_nested(&req.nh, nla); + nlattr_end_nested(&req, nla); - return libbpf_netlink_send_recv(&req.nh, NULL, NULL, NULL); + return libbpf_netlink_send_recv(&req, NULL, NULL, NULL); } int bpf_set_link_xdp_fd_opts(int ifindex, int fd, __u32 flags, @@ -314,14 +309,11 @@ int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info, struct xdp_id_md xdp_id = {}; __u32 mask; int ret; - struct { - struct nlmsghdr nh; - struct ifinfomsg ifm; - } req = { - .nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)), - .nh.nlmsg_type = RTM_GETLINK, - .nh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, - .ifm.ifi_family = AF_PACKET, + struct libbpf_nla_req req = { + .nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)), + .nh.nlmsg_type = RTM_GETLINK, + .nh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, + .ifinfo.ifi_family = AF_PACKET, }; if (flags & ~XDP_FLAGS_MASK || !info_size) @@ -336,7 +328,7 @@ int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info, xdp_id.ifindex = ifindex; xdp_id.flags = flags; - ret = libbpf_netlink_send_recv(&req.nh, __dump_link_nlmsg, + ret = libbpf_netlink_send_recv(&req, __dump_link_nlmsg, get_xdp_info, &xdp_id); if (!ret) { size_t sz = min(info_size, sizeof(xdp_id.info)); @@ -376,15 +368,14 @@ int bpf_get_link_xdp_id(int ifindex, __u32 *prog_id, __u32 flags) return libbpf_err(ret); } -typedef int (*qdisc_config_t)(struct nlmsghdr *nh, struct tcmsg *t, - size_t maxsz); +typedef int (*qdisc_config_t)(struct libbpf_nla_req *req); -static int clsact_config(struct nlmsghdr *nh, struct tcmsg *t, size_t maxsz) +static int clsact_config(struct libbpf_nla_req *req) { - t->tcm_parent = TC_H_CLSACT; - t->tcm_handle = TC_H_MAKE(TC_H_CLSACT, 0); + req->tc.tcm_parent = TC_H_CLSACT; + req->tc.tcm_handle = TC_H_MAKE(TC_H_CLSACT, 0); - return nlattr_add(nh, maxsz, TCA_KIND, "clsact", sizeof("clsact")); + return nlattr_add(req, TCA_KIND, "clsact", sizeof("clsact")); } static int attach_point_to_config(struct bpf_tc_hook *hook, @@ -431,11 +422,7 @@ static int tc_qdisc_modify(struct bpf_tc_hook *hook, int cmd, int flags) { qdisc_config_t config; int ret; - struct { - struct nlmsghdr nh; - struct tcmsg tc; - char buf[256]; - } req; + struct libbpf_nla_req req; ret = attach_point_to_config(hook, &config); if (ret < 0) @@ -448,11 +435,11 @@ static int tc_qdisc_modify(struct bpf_tc_hook *hook, int cmd, int flags) req.tc.tcm_family = AF_UNSPEC; req.tc.tcm_ifindex = OPTS_GET(hook, ifindex, 0); - ret = config(&req.nh, &req.tc, sizeof(req)); + ret = config(&req); if (ret < 0) return ret; - return libbpf_netlink_send_recv(&req.nh, NULL, NULL, NULL); + return libbpf_netlink_send_recv(&req, NULL, NULL, NULL); } static int tc_qdisc_create_excl(struct bpf_tc_hook *hook) @@ -537,14 +524,14 @@ static int get_tc_info(struct nlmsghdr *nh, libbpf_dump_nlmsg_t fn, struct nlattr *tb[TCA_MAX + 1]; libbpf_nla_parse(tb, TCA_MAX, - (struct nlattr *)((char *)tc + NLMSG_ALIGN(sizeof(*tc))), + (struct nlattr *)((void *)tc + NLMSG_ALIGN(sizeof(*tc))), NLMSG_PAYLOAD(nh, sizeof(*tc)), NULL); if (!tb[TCA_KIND]) return NL_CONT; return __get_tc_info(cookie, tc, tb, nh->nlmsg_flags & NLM_F_ECHO); } -static int tc_add_fd_and_name(struct nlmsghdr *nh, size_t maxsz, int fd) +static int tc_add_fd_and_name(struct libbpf_nla_req *req, int fd) { struct bpf_prog_info info = {}; __u32 info_len = sizeof(info); @@ -555,7 +542,7 @@ static int tc_add_fd_and_name(struct nlmsghdr *nh, size_t maxsz, int fd) if (ret < 0) return ret; - ret = nlattr_add(nh, maxsz, TCA_BPF_FD, &fd, sizeof(fd)); + ret = nlattr_add(req, TCA_BPF_FD, &fd, sizeof(fd)); if (ret < 0) return ret; len = snprintf(name, sizeof(name), "%s:[%u]", info.name, info.id); @@ -563,7 +550,7 @@ static int tc_add_fd_and_name(struct nlmsghdr *nh, size_t maxsz, int fd) return -errno; if (len >= sizeof(name)) return -ENAMETOOLONG; - return nlattr_add(nh, maxsz, TCA_BPF_NAME, name, len + 1); + return nlattr_add(req, TCA_BPF_NAME, name, len + 1); } int bpf_tc_attach(const struct bpf_tc_hook *hook, struct bpf_tc_opts *opts) @@ -571,12 +558,8 @@ int bpf_tc_attach(const struct bpf_tc_hook *hook, struct bpf_tc_opts *opts) __u32 protocol, bpf_flags, handle, priority, parent, prog_id, flags; int ret, ifindex, attach_point, prog_fd; struct bpf_cb_ctx info = {}; + struct libbpf_nla_req req; struct nlattr *nla; - struct { - struct nlmsghdr nh; - struct tcmsg tc; - char buf[256]; - } req; if (!hook || !opts || !OPTS_VALID(hook, bpf_tc_hook) || @@ -618,25 +601,24 @@ int bpf_tc_attach(const struct bpf_tc_hook *hook, struct bpf_tc_opts *opts) return libbpf_err(ret); req.tc.tcm_parent = parent; - ret = nlattr_add(&req.nh, sizeof(req), TCA_KIND, "bpf", sizeof("bpf")); + ret = nlattr_add(&req, TCA_KIND, "bpf", sizeof("bpf")); if (ret < 0) return libbpf_err(ret); - nla = nlattr_begin_nested(&req.nh, sizeof(req), TCA_OPTIONS); + nla = nlattr_begin_nested(&req, TCA_OPTIONS); if (!nla) return libbpf_err(-EMSGSIZE); - ret = tc_add_fd_and_name(&req.nh, sizeof(req), prog_fd); + ret = tc_add_fd_and_name(&req, prog_fd); if (ret < 0) return libbpf_err(ret); bpf_flags = TCA_BPF_FLAG_ACT_DIRECT; - ret = nlattr_add(&req.nh, sizeof(req), TCA_BPF_FLAGS, &bpf_flags, - sizeof(bpf_flags)); + ret = nlattr_add(&req, TCA_BPF_FLAGS, &bpf_flags, sizeof(bpf_flags)); if (ret < 0) return libbpf_err(ret); - nlattr_end_nested(&req.nh, nla); + nlattr_end_nested(&req, nla); info.opts = opts; - ret = libbpf_netlink_send_recv(&req.nh, get_tc_info, NULL, &info); + ret = libbpf_netlink_send_recv(&req, get_tc_info, NULL, &info); if (ret < 0) return libbpf_err(ret); if (!info.processed) @@ -650,11 +632,7 @@ static int __bpf_tc_detach(const struct bpf_tc_hook *hook, { __u32 protocol = 0, handle, priority, parent, prog_id, flags; int ret, ifindex, attach_point, prog_fd; - struct { - struct nlmsghdr nh; - struct tcmsg tc; - char buf[256]; - } req; + struct libbpf_nla_req req; if (!hook || !OPTS_VALID(hook, bpf_tc_hook) || @@ -701,13 +679,12 @@ static int __bpf_tc_detach(const struct bpf_tc_hook *hook, req.tc.tcm_parent = parent; if (!flush) { - ret = nlattr_add(&req.nh, sizeof(req), TCA_KIND, - "bpf", sizeof("bpf")); + ret = nlattr_add(&req, TCA_KIND, "bpf", sizeof("bpf")); if (ret < 0) return ret; } - return libbpf_netlink_send_recv(&req.nh, NULL, NULL, NULL); + return libbpf_netlink_send_recv(&req, NULL, NULL, NULL); } int bpf_tc_detach(const struct bpf_tc_hook *hook, @@ -727,11 +704,7 @@ int bpf_tc_query(const struct bpf_tc_hook *hook, struct bpf_tc_opts *opts) __u32 protocol, handle, priority, parent, prog_id, flags; int ret, ifindex, attach_point, prog_fd; struct bpf_cb_ctx info = {}; - struct { - struct nlmsghdr nh; - struct tcmsg tc; - char buf[256]; - } req; + struct libbpf_nla_req req; if (!hook || !opts || !OPTS_VALID(hook, bpf_tc_hook) || @@ -770,13 +743,13 @@ int bpf_tc_query(const struct bpf_tc_hook *hook, struct bpf_tc_opts *opts) return libbpf_err(ret); req.tc.tcm_parent = parent; - ret = nlattr_add(&req.nh, sizeof(req), TCA_KIND, "bpf", sizeof("bpf")); + ret = nlattr_add(&req, TCA_KIND, "bpf", sizeof("bpf")); if (ret < 0) return libbpf_err(ret); info.opts = opts; - ret = libbpf_netlink_send_recv(&req.nh, get_tc_info, NULL, &info); + ret = libbpf_netlink_send_recv(&req, get_tc_info, NULL, &info); if (ret < 0) return libbpf_err(ret); if (!info.processed) diff --git a/tools/lib/bpf/nlattr.c b/tools/lib/bpf/nlattr.c index b607fa9852b1..f57e77a6e40f 100644 --- a/tools/lib/bpf/nlattr.c +++ b/tools/lib/bpf/nlattr.c @@ -27,7 +27,7 @@ static struct nlattr *nla_next(const struct nlattr *nla, int *remaining) int totlen = NLA_ALIGN(nla->nla_len); *remaining -= totlen; - return (struct nlattr *) ((char *) nla + totlen); + return (struct nlattr *)((void *)nla + totlen); } static int nla_ok(const struct nlattr *nla, int remaining) diff --git a/tools/lib/bpf/nlattr.h b/tools/lib/bpf/nlattr.h index 3c780ab6d022..4d15ae2ff812 100644 --- a/tools/lib/bpf/nlattr.h +++ b/tools/lib/bpf/nlattr.h @@ -13,6 +13,7 @@ #include <string.h> #include <errno.h> #include <linux/netlink.h> +#include <linux/rtnetlink.h> /* avoid multiple definition of netlink features */ #define __LINUX_NETLINK_H @@ -52,6 +53,15 @@ struct libbpf_nla_policy { uint16_t maxlen; }; +struct libbpf_nla_req { + struct nlmsghdr nh; + union { + struct ifinfomsg ifinfo; + struct tcmsg tc; + }; + char buf[128]; +}; + /** * @ingroup attr * Iterate over a stream of attributes @@ -71,7 +81,7 @@ struct libbpf_nla_policy { */ static inline void *libbpf_nla_data(const struct nlattr *nla) { - return (char *) nla + NLA_HDRLEN; + return (void *)nla + NLA_HDRLEN; } static inline uint8_t libbpf_nla_getattr_u8(const struct nlattr *nla) @@ -108,47 +118,47 @@ int libbpf_nla_dump_errormsg(struct nlmsghdr *nlh); static inline struct nlattr *nla_data(struct nlattr *nla) { - return (struct nlattr *)((char *)nla + NLA_HDRLEN); + return (struct nlattr *)((void *)nla + NLA_HDRLEN); } -static inline struct nlattr *nh_tail(struct nlmsghdr *nh) +static inline struct nlattr *req_tail(struct libbpf_nla_req *req) { - return (struct nlattr *)((char *)nh + NLMSG_ALIGN(nh->nlmsg_len)); + return (struct nlattr *)((void *)req + NLMSG_ALIGN(req->nh.nlmsg_len)); } -static inline int nlattr_add(struct nlmsghdr *nh, size_t maxsz, int type, +static inline int nlattr_add(struct libbpf_nla_req *req, int type, const void *data, int len) { struct nlattr *nla; - if (NLMSG_ALIGN(nh->nlmsg_len) + NLA_ALIGN(NLA_HDRLEN + len) > maxsz) + if (NLMSG_ALIGN(req->nh.nlmsg_len) + NLA_ALIGN(NLA_HDRLEN + len) > sizeof(*req)) return -EMSGSIZE; if (!!data != !!len) return -EINVAL; - nla = nh_tail(nh); + nla = req_tail(req); nla->nla_type = type; nla->nla_len = NLA_HDRLEN + len; if (data) memcpy(nla_data(nla), data, len); - nh->nlmsg_len = NLMSG_ALIGN(nh->nlmsg_len) + NLA_ALIGN(nla->nla_len); + req->nh.nlmsg_len = NLMSG_ALIGN(req->nh.nlmsg_len) + NLA_ALIGN(nla->nla_len); return 0; } -static inline struct nlattr *nlattr_begin_nested(struct nlmsghdr *nh, - size_t maxsz, int type) +static inline struct nlattr *nlattr_begin_nested(struct libbpf_nla_req *req, int type) { struct nlattr *tail; - tail = nh_tail(nh); - if (nlattr_add(nh, maxsz, type | NLA_F_NESTED, NULL, 0)) + tail = req_tail(req); + if (nlattr_add(req, type | NLA_F_NESTED, NULL, 0)) return NULL; return tail; } -static inline void nlattr_end_nested(struct nlmsghdr *nh, struct nlattr *tail) +static inline void nlattr_end_nested(struct libbpf_nla_req *req, + struct nlattr *tail) { - tail->nla_len = (char *)nh_tail(nh) - (char *)tail; + tail->nla_len = (void *)req_tail(req) - (void *)tail; } #endif /* __LIBBPF_NLATTR_H */ diff --git a/tools/testing/selftests/bpf/prog_tests/ringbuf.c b/tools/testing/selftests/bpf/prog_tests/ringbuf.c index a01788090c31..4706cee84360 100644 --- a/tools/testing/selftests/bpf/prog_tests/ringbuf.c +++ b/tools/testing/selftests/bpf/prog_tests/ringbuf.c @@ -100,7 +100,7 @@ void test_ringbuf(void) if (CHECK(err != 0, "skel_load", "skeleton load failed\n")) goto cleanup; - rb_fd = bpf_map__fd(skel->maps.ringbuf); + rb_fd = skel->maps.ringbuf.map_fd; /* good read/write cons_pos */ mmap_ptr = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, rb_fd, 0); ASSERT_OK_PTR(mmap_ptr, "rw_cons_pos"); |