sf_buf.h revision 270201
1/*-
2 * Copyright (c) 2014 Gleb Smirnoff <glebius@FreeBSD.org>
3 * Copyright (c) 2003-2004 Alan L. Cox <alc@cs.rice.edu>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * $FreeBSD: head/sys/sys/sf_buf.h 270201 2014-08-20 08:02:38Z kib $
28 */
29
30#ifndef _SYS_SF_BUF_H_
31#define _SYS_SF_BUF_H_
32
33struct sfstat {				/* sendfile statistics */
34	uint64_t	sf_iocnt;	/* times sendfile had to do disk I/O */
35	uint64_t	sf_allocfail;	/* times sfbuf allocation failed */
36	uint64_t	sf_allocwait;	/* times sfbuf allocation had to wait */
37};
38
39#ifdef _KERNEL
40#include <sys/types.h>
41#include <sys/systm.h>
42#include <sys/counter.h>
43#include <vm/vm.h>
44#include <vm/vm_param.h>
45#include <vm/vm_page.h>
46
47/*
48 * Sf_bufs, or sendfile(2) buffers provide a vm_page that is mapped
49 * into kernel address space. Note, that they aren't used only
50 * by sendfile(2)!
51 *
52 * Sf_bufs could be implemented as a feature of vm_page_t, but that
53 * would require growth of the structure. That's why they are implemented
54 * as a separate hash indexed by vm_page address. Implementation lives in
55 * kern/subr_sfbuf.c. Meanwhile, most 64-bit machines have a physical map,
56 * so they don't require this hash at all, thus ignore subr_sfbuf.c.
57 *
58 * Different 32-bit architectures demand different requirements on sf_buf
59 * hash and functions. They request features in machine/vmparam.h, which
60 * enable parts of this file. They can also optionally provide helpers in
61 * machine/sf_buf.h
62 *
63 * Defines are:
64 * SFBUF		This machine requires sf_buf hash.
65 * 			subr_sfbuf.c should be compiled.
66 * SFBUF_CPUSET		This machine can perform SFB_CPUPRIVATE mappings,
67 *			that do no invalidate cache on the rest of CPUs.
68 * SFBUF_NOMD		This machine doesn't have machine/sf_buf.h
69 *
70 * SFBUF_OPTIONAL_DIRECT_MAP	Value of this define is used as boolean
71 *				variable that tells whether machine is
72 *				capable of direct map or not at runtime.
73 * SFBUF_MAP		This machine provides its own sf_buf_map() and
74 *			sf_buf_unmap().
75 * SFBUF_PROCESS_PAGE	This machine provides sf_buf_process_page()
76 *			function.
77 */
78
79#ifdef SFBUF
80#if defined(SMP) && defined(SFBUF_CPUSET)
81#include <sys/_cpuset.h>
82#endif
83#include <sys/queue.h>
84
85struct sf_buf {
86	LIST_ENTRY(sf_buf)	list_entry;	/* list of buffers */
87	TAILQ_ENTRY(sf_buf)	free_entry;	/* list of buffers */
88	vm_page_t		m;		/* currently mapped page */
89	vm_offset_t		kva;		/* va of mapping */
90	int			ref_count;	/* usage of this mapping */
91#if defined(SMP) && defined(SFBUF_CPUSET)
92	cpuset_t		cpumask;	/* where mapping is valid */
93#endif
94};
95#else /* ! SFBUF */
96struct sf_buf;
97#endif /* SFBUF */
98
99#ifndef SFBUF_NOMD
100#include <machine/sf_buf.h>
101#endif
102#ifdef SFBUF_OPTIONAL_DIRECT_MAP
103#include <machine/md_var.h>
104#endif
105
106#ifdef SFBUF
107struct sf_buf *sf_buf_alloc(struct vm_page *, int);
108void sf_buf_free(struct sf_buf *);
109void sf_buf_ref(struct sf_buf *);
110
111static inline vm_offset_t
112sf_buf_kva(struct sf_buf *sf)
113{
114#ifdef SFBUF_OPTIONAL_DIRECT_MAP
115	if (SFBUF_OPTIONAL_DIRECT_MAP)
116		return (SFBUF_PHYS_DMAP(VM_PAGE_TO_PHYS((vm_page_t)sf)));
117#endif
118
119        return (sf->kva);
120}
121
122static inline vm_page_t
123sf_buf_page(struct sf_buf *sf)
124{
125#ifdef SFBUF_OPTIONAL_DIRECT_MAP
126	if (SFBUF_OPTIONAL_DIRECT_MAP)
127		return ((vm_page_t)sf);
128#endif
129
130        return (sf->m);
131}
132
133#ifndef SFBUF_MAP
134#include <vm/pmap.h>
135
136static inline void
137sf_buf_map(struct sf_buf *sf, int flags)
138{
139
140	pmap_qenter(sf->kva, &sf->m, 1);
141}
142
143static inline int
144sf_buf_unmap(struct sf_buf *sf)
145{
146
147	return (0);
148}
149#endif /* SFBUF_MAP */
150
151#if defined(SMP) && defined(SFBUF_CPUSET)
152void sf_buf_shootdown(struct sf_buf *, int);
153#endif
154
155#ifdef SFBUF_PROCESS_PAGE
156boolean_t sf_buf_process_page(vm_page_t, void (*)(struct sf_buf *));
157#endif
158
159#else /* ! SFBUF */
160
161static inline struct sf_buf *
162sf_buf_alloc(struct vm_page *m, int pri)
163{
164
165	return ((struct sf_buf *)m);
166}
167
168static inline void
169sf_buf_free(struct sf_buf *sf)
170{
171}
172
173static inline void
174sf_buf_ref(struct sf_buf *sf)
175{
176}
177#endif /* SFBUF */
178
179/*
180 * Options to sf_buf_alloc() are specified through its flags argument.  This
181 * argument's value should be the result of a bitwise or'ing of one or more
182 * of the following values.
183 */
184#define	SFB_CATCH	1		/* Check signals if the allocation
185					   sleeps. */
186#define	SFB_CPUPRIVATE	2		/* Create a CPU private mapping. */
187#define	SFB_DEFAULT	0
188#define	SFB_NOWAIT	4		/* Return NULL if all bufs are used. */
189
190extern counter_u64_t sfstat[sizeof(struct sfstat) / sizeof(uint64_t)];
191#define	SFSTAT_ADD(name, val)	\
192    counter_u64_add(sfstat[offsetof(struct sfstat, name) / sizeof(uint64_t)],\
193	(val))
194#define	SFSTAT_INC(name)	SFSTAT_ADD(name, 1)
195#endif /* _KERNEL */
196#endif /* !_SYS_SF_BUF_H_ */
197