1122780Salc/*- 2269577Sglebius * Copyright (c) 2014 Gleb Smirnoff <glebius@FreeBSD.org> 3137372Salc * Copyright (c) 2003-2004 Alan L. Cox <alc@cs.rice.edu> 4122780Salc * All rights reserved. 5122780Salc * 6122780Salc * Redistribution and use in source and binary forms, with or without 7122780Salc * modification, are permitted provided that the following conditions 8122780Salc * are met: 9122780Salc * 1. Redistributions of source code must retain the above copyright 10122780Salc * notice, this list of conditions and the following disclaimer. 11122780Salc * 2. Redistributions in binary form must reproduce the above copyright 12122780Salc * notice, this list of conditions and the following disclaimer in the 13122780Salc * documentation and/or other materials provided with the distribution. 14122780Salc * 15122780Salc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16122780Salc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17122780Salc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18122780Salc * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19122780Salc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20122780Salc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21122780Salc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22122780Salc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23122780Salc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24122780Salc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25122780Salc * SUCH DAMAGE. 26122780Salc * 27122780Salc * $FreeBSD$ 28122780Salc */ 29122780Salc 30122780Salc#ifndef _SYS_SF_BUF_H_ 31122780Salc#define _SYS_SF_BUF_H_ 32122780Salc 33269577Sglebiusstruct sfstat { /* sendfile statistics */ 34293439Sglebius uint64_t sf_syscalls; /* times sendfile was called */ 35293439Sglebius uint64_t sf_noiocnt; /* times sendfile didn't require I/O */ 36269577Sglebius uint64_t sf_iocnt; /* times sendfile had to do disk I/O */ 37293439Sglebius uint64_t sf_pages_read; /* pages read as part of a request */ 38293439Sglebius uint64_t sf_pages_valid; /* pages were valid for a request */ 39293439Sglebius uint64_t sf_rhpages_requested; /* readahead pages requested */ 40293439Sglebius uint64_t sf_rhpages_read; /* readahead pages read */ 41293439Sglebius uint64_t sf_busy; /* times aborted on a busy page */ 42269577Sglebius uint64_t sf_allocfail; /* times sfbuf allocation failed */ 43269577Sglebius uint64_t sf_allocwait; /* times sfbuf allocation had to wait */ 44269577Sglebius}; 45269577Sglebius 46269577Sglebius#ifdef _KERNEL 47269577Sglebius#include <sys/types.h> 48269577Sglebius#include <sys/systm.h> 49269577Sglebius#include <sys/counter.h> 50269577Sglebius#include <vm/vm.h> 51269577Sglebius#include <vm/vm_param.h> 52269577Sglebius#include <vm/vm_page.h> 53269577Sglebius 54137372Salc/* 55269577Sglebius * Sf_bufs, or sendfile(2) buffers provide a vm_page that is mapped 56269577Sglebius * into kernel address space. Note, that they aren't used only 57269577Sglebius * by sendfile(2)! 58269577Sglebius * 59269577Sglebius * Sf_bufs could be implemented as a feature of vm_page_t, but that 60269577Sglebius * would require growth of the structure. That's why they are implemented 61269577Sglebius * as a separate hash indexed by vm_page address. Implementation lives in 62269577Sglebius * kern/subr_sfbuf.c. Meanwhile, most 64-bit machines have a physical map, 63269577Sglebius * so they don't require this hash at all, thus ignore subr_sfbuf.c. 64269577Sglebius * 65269577Sglebius * Different 32-bit architectures demand different requirements on sf_buf 66269577Sglebius * hash and functions. They request features in machine/vmparam.h, which 67269577Sglebius * enable parts of this file. They can also optionally provide helpers in 68269577Sglebius * machine/sf_buf.h 69269577Sglebius * 70269577Sglebius * Defines are: 71269577Sglebius * SFBUF This machine requires sf_buf hash. 72269577Sglebius * subr_sfbuf.c should be compiled. 73269577Sglebius * SFBUF_CPUSET This machine can perform SFB_CPUPRIVATE mappings, 74269577Sglebius * that do no invalidate cache on the rest of CPUs. 75269577Sglebius * SFBUF_NOMD This machine doesn't have machine/sf_buf.h 76269577Sglebius * 77269577Sglebius * SFBUF_OPTIONAL_DIRECT_MAP Value of this define is used as boolean 78269577Sglebius * variable that tells whether machine is 79269577Sglebius * capable of direct map or not at runtime. 80269577Sglebius * SFBUF_MAP This machine provides its own sf_buf_map() and 81269577Sglebius * sf_buf_unmap(). 82269577Sglebius * SFBUF_PROCESS_PAGE This machine provides sf_buf_process_page() 83269577Sglebius * function. 84269577Sglebius */ 85269577Sglebius 86269577Sglebius#ifdef SFBUF 87269577Sglebius#if defined(SMP) && defined(SFBUF_CPUSET) 88269577Sglebius#include <sys/_cpuset.h> 89269577Sglebius#endif 90269577Sglebius#include <sys/queue.h> 91269577Sglebius 92269577Sglebiusstruct sf_buf { 93269577Sglebius LIST_ENTRY(sf_buf) list_entry; /* list of buffers */ 94269577Sglebius TAILQ_ENTRY(sf_buf) free_entry; /* list of buffers */ 95269577Sglebius vm_page_t m; /* currently mapped page */ 96269577Sglebius vm_offset_t kva; /* va of mapping */ 97269577Sglebius int ref_count; /* usage of this mapping */ 98269577Sglebius#if defined(SMP) && defined(SFBUF_CPUSET) 99269577Sglebius cpuset_t cpumask; /* where mapping is valid */ 100269577Sglebius#endif 101269577Sglebius}; 102269577Sglebius#else /* ! SFBUF */ 103269577Sglebiusstruct sf_buf; 104269577Sglebius#endif /* SFBUF */ 105269577Sglebius 106269577Sglebius#ifndef SFBUF_NOMD 107269577Sglebius#include <machine/sf_buf.h> 108269577Sglebius#endif 109269577Sglebius#ifdef SFBUF_OPTIONAL_DIRECT_MAP 110269577Sglebius#include <machine/md_var.h> 111269577Sglebius#endif 112269577Sglebius 113269577Sglebius#ifdef SFBUF 114269577Sglebiusstruct sf_buf *sf_buf_alloc(struct vm_page *, int); 115269577Sglebiusvoid sf_buf_free(struct sf_buf *); 116269807Sglebiusvoid sf_buf_ref(struct sf_buf *); 117269577Sglebius 118269577Sglebiusstatic inline vm_offset_t 119269577Sglebiussf_buf_kva(struct sf_buf *sf) 120269577Sglebius{ 121269577Sglebius#ifdef SFBUF_OPTIONAL_DIRECT_MAP 122269577Sglebius if (SFBUF_OPTIONAL_DIRECT_MAP) 123270201Skib return (SFBUF_PHYS_DMAP(VM_PAGE_TO_PHYS((vm_page_t)sf))); 124269577Sglebius#endif 125269577Sglebius 126269577Sglebius return (sf->kva); 127269577Sglebius} 128269577Sglebius 129269577Sglebiusstatic inline vm_page_t 130269577Sglebiussf_buf_page(struct sf_buf *sf) 131269577Sglebius{ 132269577Sglebius#ifdef SFBUF_OPTIONAL_DIRECT_MAP 133269577Sglebius if (SFBUF_OPTIONAL_DIRECT_MAP) 134269577Sglebius return ((vm_page_t)sf); 135269577Sglebius#endif 136269577Sglebius 137269577Sglebius return (sf->m); 138269577Sglebius} 139269577Sglebius 140269577Sglebius#ifndef SFBUF_MAP 141269577Sglebius#include <vm/pmap.h> 142269577Sglebius 143269577Sglebiusstatic inline void 144269577Sglebiussf_buf_map(struct sf_buf *sf, int flags) 145269577Sglebius{ 146269577Sglebius 147269577Sglebius pmap_qenter(sf->kva, &sf->m, 1); 148269577Sglebius} 149269577Sglebius 150269577Sglebiusstatic inline int 151269577Sglebiussf_buf_unmap(struct sf_buf *sf) 152269577Sglebius{ 153269577Sglebius 154269577Sglebius return (0); 155269577Sglebius} 156269577Sglebius#endif /* SFBUF_MAP */ 157269577Sglebius 158269577Sglebius#if defined(SMP) && defined(SFBUF_CPUSET) 159269577Sglebiusvoid sf_buf_shootdown(struct sf_buf *, int); 160269577Sglebius#endif 161269577Sglebius 162269577Sglebius#ifdef SFBUF_PROCESS_PAGE 163269577Sglebiusboolean_t sf_buf_process_page(vm_page_t, void (*)(struct sf_buf *)); 164269577Sglebius#endif 165269577Sglebius 166269577Sglebius#else /* ! SFBUF */ 167269577Sglebius 168269577Sglebiusstatic inline struct sf_buf * 169269577Sglebiussf_buf_alloc(struct vm_page *m, int pri) 170269577Sglebius{ 171269577Sglebius 172269577Sglebius return ((struct sf_buf *)m); 173269577Sglebius} 174269577Sglebius 175269577Sglebiusstatic inline void 176269577Sglebiussf_buf_free(struct sf_buf *sf) 177269577Sglebius{ 178269577Sglebius} 179269807Sglebius 180269807Sglebiusstatic inline void 181269807Sglebiussf_buf_ref(struct sf_buf *sf) 182269807Sglebius{ 183269807Sglebius} 184269577Sglebius#endif /* SFBUF */ 185269577Sglebius 186269577Sglebius/* 187137372Salc * Options to sf_buf_alloc() are specified through its flags argument. This 188137372Salc * argument's value should be the result of a bitwise or'ing of one or more 189137372Salc * of the following values. 190137372Salc */ 191137372Salc#define SFB_CATCH 1 /* Check signals if the allocation 192137372Salc sleeps. */ 193137372Salc#define SFB_CPUPRIVATE 2 /* Create a CPU private mapping. */ 194137372Salc#define SFB_DEFAULT 0 195137372Salc#define SFB_NOWAIT 4 /* Return NULL if all bufs are used. */ 196137372Salc 197253351Saeextern counter_u64_t sfstat[sizeof(struct sfstat) / sizeof(uint64_t)]; 198253351Sae#define SFSTAT_ADD(name, val) \ 199253351Sae counter_u64_add(sfstat[offsetof(struct sfstat, name) / sizeof(uint64_t)],\ 200253351Sae (val)) 201253351Sae#define SFSTAT_INC(name) SFSTAT_ADD(name, 1) 202253351Sae#endif /* _KERNEL */ 203122780Salc#endif /* !_SYS_SF_BUF_H_ */ 204