diff options
author | glebius <glebius@FreeBSD.org> | 2014-08-05 09:44:10 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2014-08-05 09:44:10 +0000 |
commit | 991a1f338d51c4c8f87ae530a1142a92f1626c96 (patch) | |
tree | 4d877314a59ae549347eb85276851e4a8dce37a7 /sys/sys/sf_buf.h | |
parent | 7cb9d0139b7fbaa1a047ddb52ee3674df1c313f4 (diff) | |
download | FreeBSD-src-991a1f338d51c4c8f87ae530a1142a92f1626c96.zip FreeBSD-src-991a1f338d51c4c8f87ae530a1142a92f1626c96.tar.gz |
Merge all MD sf_buf allocators into one MI, residing in kern/subr_sfbuf.c
The MD allocators were very common, however there were some minor
differencies. These differencies were all consolidated in the MI allocator,
under ifdefs. The defines from machine/vmparam.h turn on features required
for a particular machine. For details look in the comment in sys/sf_buf.h.
As result no MD code left in sys/*/*/vm_machdep.c. Some arches still have
machine/sf_buf.h, which is usually quite small.
Tested by: glebius (i386), tuexen (arm32), kevlo (arm32)
Reviewed by: kib
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
Diffstat (limited to 'sys/sys/sf_buf.h')
-rw-r--r-- | sys/sys/sf_buf.h | 154 |
1 files changed, 141 insertions, 13 deletions
diff --git a/sys/sys/sf_buf.h b/sys/sys/sf_buf.h index 07871dd..8a6c56f 100644 --- a/sys/sys/sf_buf.h +++ b/sys/sys/sf_buf.h @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2014 Gleb Smirnoff <glebius@FreeBSD.org> * Copyright (c) 2003-2004 Alan L. Cox <alc@cs.rice.edu> * All rights reserved. * @@ -29,6 +30,146 @@ #ifndef _SYS_SF_BUF_H_ #define _SYS_SF_BUF_H_ +struct sfstat { /* sendfile statistics */ + uint64_t sf_iocnt; /* times sendfile had to do disk I/O */ + uint64_t sf_allocfail; /* times sfbuf allocation failed */ + uint64_t sf_allocwait; /* times sfbuf allocation had to wait */ +}; + +#ifdef _KERNEL +#include <sys/types.h> +#include <sys/systm.h> +#include <sys/counter.h> +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/vm_page.h> + +/* + * Sf_bufs, or sendfile(2) buffers provide a vm_page that is mapped + * into kernel address space. Note, that they aren't used only + * by sendfile(2)! + * + * Sf_bufs could be implemented as a feature of vm_page_t, but that + * would require growth of the structure. That's why they are implemented + * as a separate hash indexed by vm_page address. Implementation lives in + * kern/subr_sfbuf.c. Meanwhile, most 64-bit machines have a physical map, + * so they don't require this hash at all, thus ignore subr_sfbuf.c. + * + * Different 32-bit architectures demand different requirements on sf_buf + * hash and functions. They request features in machine/vmparam.h, which + * enable parts of this file. They can also optionally provide helpers in + * machine/sf_buf.h + * + * Defines are: + * SFBUF This machine requires sf_buf hash. + * subr_sfbuf.c should be compiled. + * SFBUF_CPUSET This machine can perform SFB_CPUPRIVATE mappings, + * that do no invalidate cache on the rest of CPUs. + * SFBUF_NOMD This machine doesn't have machine/sf_buf.h + * + * SFBUF_OPTIONAL_DIRECT_MAP Value of this define is used as boolean + * variable that tells whether machine is + * capable of direct map or not at runtime. + * SFBUF_MAP This machine provides its own sf_buf_map() and + * sf_buf_unmap(). + * SFBUF_PROCESS_PAGE This machine provides sf_buf_process_page() + * function. + */ + +#ifdef SFBUF +#if defined(SMP) && defined(SFBUF_CPUSET) +#include <sys/_cpuset.h> +#endif +#include <sys/queue.h> + +struct sf_buf { + LIST_ENTRY(sf_buf) list_entry; /* list of buffers */ + TAILQ_ENTRY(sf_buf) free_entry; /* list of buffers */ + vm_page_t m; /* currently mapped page */ + vm_offset_t kva; /* va of mapping */ + int ref_count; /* usage of this mapping */ +#if defined(SMP) && defined(SFBUF_CPUSET) + cpuset_t cpumask; /* where mapping is valid */ +#endif +}; +#else /* ! SFBUF */ +struct sf_buf; +#endif /* SFBUF */ + +#ifndef SFBUF_NOMD +#include <machine/sf_buf.h> +#endif +#ifdef SFBUF_OPTIONAL_DIRECT_MAP +#include <machine/md_var.h> +#endif + +#ifdef SFBUF +struct sf_buf *sf_buf_alloc(struct vm_page *, int); +void sf_buf_free(struct sf_buf *); + +static inline vm_offset_t +sf_buf_kva(struct sf_buf *sf) +{ +#ifdef SFBUF_OPTIONAL_DIRECT_MAP + if (SFBUF_OPTIONAL_DIRECT_MAP) + return (VM_PAGE_TO_PHYS((vm_page_t)sf)); +#endif + + return (sf->kva); +} + +static inline vm_page_t +sf_buf_page(struct sf_buf *sf) +{ +#ifdef SFBUF_OPTIONAL_DIRECT_MAP + if (SFBUF_OPTIONAL_DIRECT_MAP) + return ((vm_page_t)sf); +#endif + + return (sf->m); +} + +#ifndef SFBUF_MAP +#include <vm/pmap.h> + +static inline void +sf_buf_map(struct sf_buf *sf, int flags) +{ + + pmap_qenter(sf->kva, &sf->m, 1); +} + +static inline int +sf_buf_unmap(struct sf_buf *sf) +{ + + return (0); +} +#endif /* SFBUF_MAP */ + +#if defined(SMP) && defined(SFBUF_CPUSET) +void sf_buf_shootdown(struct sf_buf *, int); +#endif + +#ifdef SFBUF_PROCESS_PAGE +boolean_t sf_buf_process_page(vm_page_t, void (*)(struct sf_buf *)); +#endif + +#else /* ! SFBUF */ + +static inline struct sf_buf * +sf_buf_alloc(struct vm_page *m, int pri) +{ + + return ((struct sf_buf *)m); +} + +static inline void +sf_buf_free(struct sf_buf *sf) +{ +} +#endif /* SFBUF */ + /* * Options to sf_buf_alloc() are specified through its flags argument. This * argument's value should be the result of a bitwise or'ing of one or more @@ -40,19 +181,6 @@ #define SFB_DEFAULT 0 #define SFB_NOWAIT 4 /* Return NULL if all bufs are used. */ -struct vm_page; - -struct sfstat { /* sendfile statistics */ - uint64_t sf_iocnt; /* times sendfile had to do disk I/O */ - uint64_t sf_allocfail; /* times sfbuf allocation failed */ - uint64_t sf_allocwait; /* times sfbuf allocation had to wait */ -}; - -#ifdef _KERNEL -#include <machine/sf_buf.h> -#include <sys/systm.h> -#include <sys/counter.h> - extern counter_u64_t sfstat[sizeof(struct sfstat) / sizeof(uint64_t)]; #define SFSTAT_ADD(name, val) \ counter_u64_add(sfstat[offsetof(struct sfstat, name) / sizeof(uint64_t)],\ |