1c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/*
2c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * linux/include/linux/relay.h
3c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
4c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * Copyright (C) 2002, 2003 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp
5c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * Copyright (C) 1999, 2000, 2001, 2002 - Karim Yaghmour (karim@opersys.com)
6c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
7c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * CONFIG_RELAY definitions and declarations
8c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
9c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
10c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#ifndef _LINUX_RELAY_H
11c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define _LINUX_RELAY_H
12c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
13c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <linux/types.h>
14c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <linux/sched.h>
15c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <linux/wait.h>
16c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <linux/list.h>
17c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <linux/fs.h>
18c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <linux/poll.h>
19c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#include <linux/kref.h>
20c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
21c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/* Needs a _much_ better name... */
22c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define FIX_SIZE(x) ((((x) - 1) & PAGE_MASK) + PAGE_SIZE)
23c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
24c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/*
25c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * Tracks changes to rchan/rchan_buf structs
26c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
27c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#define RELAYFS_CHANNEL_VERSION		6
28c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
29c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/*
30c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * Per-cpu relay channel buffer
31c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
32c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct rchan_buf
33c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
34c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	void *start;			/* start of channel buffer */
35c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	void *data;			/* start of current sub-buffer */
36c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	size_t offset;			/* current offset into sub-buffer */
37c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	size_t subbufs_produced;	/* count of sub-buffers produced */
38c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	size_t subbufs_consumed;	/* count of sub-buffers consumed */
39c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct rchan *chan;		/* associated channel */
40c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	wait_queue_head_t read_wait;	/* reader wait queue */
41c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct work_struct wake_readers; /* reader wake-up work struct */
42c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct dentry *dentry;		/* channel file dentry */
43c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct kref kref;		/* channel buffer refcount */
44c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct page **page_array;	/* array of current buffer pages */
45c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	unsigned int page_count;	/* number of current buffer pages */
46c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	unsigned int finalized;		/* buffer has been finalized */
47c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	size_t *padding;		/* padding counts per sub-buffer */
48c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	size_t prev_padding;		/* temporary variable */
49c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	size_t bytes_consumed;		/* bytes consumed in cur read subbuf */
50c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	unsigned int cpu;		/* this buf's cpu */
51c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru} ____cacheline_aligned;
52c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
53c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/*
54c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * Relay channel data structure
55c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
56c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct rchan
57c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
58c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	u32 version;			/* the version of this struct */
59c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	size_t subbuf_size;		/* sub-buffer size */
60c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	size_t n_subbufs;		/* number of sub-buffers per buffer */
61c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	size_t alloc_size;		/* total buffer size allocated */
62c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct rchan_callbacks *cb;	/* client callbacks */
63c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct kref kref;		/* channel refcount */
64c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	void *private_data;		/* for user-defined data */
65c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	size_t last_toobig;		/* tried to log event > subbuf size */
66c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct rchan_buf *buf[NR_CPUS]; /* per-cpu channel buffers */
67c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru};
68c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
69c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/*
70c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * Relay channel client callbacks
71c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
72c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct rchan_callbacks
73c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
74c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	/*
75c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * subbuf_start - called on buffer-switch to a new sub-buffer
76c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * @buf: the channel buffer containing the new sub-buffer
77c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * @subbuf: the start of the new sub-buffer
78c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * @prev_subbuf: the start of the previous sub-buffer
79c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * @prev_padding: unused space at the end of previous sub-buffer
80c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 *
81c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * The client should return 1 to continue logging, 0 to stop
82c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * logging.
83c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 *
84c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * NOTE: subbuf_start will also be invoked when the buffer is
85c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 *       created, so that the first sub-buffer can be initialized
86c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 *       if necessary.  In this case, prev_subbuf will be NULL.
87c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 *
88c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * NOTE: the client can reserve bytes at the beginning of the new
89c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 *       sub-buffer by calling subbuf_start_reserve() in this callback.
90c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 */
91c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int (*subbuf_start) (struct rchan_buf *buf,
92c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			     void *subbuf,
93c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			     void *prev_subbuf,
94c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			     size_t prev_padding);
95c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
96c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	/*
97c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * buf_mapped - relay buffer mmap notification
98c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * @buf: the channel buffer
99c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * @filp: relay file pointer
100c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 *
101c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * Called when a relay file is successfully mmapped
102c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 */
103c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru        void (*buf_mapped)(struct rchan_buf *buf,
104c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			   struct file *filp);
105c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
106c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	/*
107c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * buf_unmapped - relay buffer unmap notification
108c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * @buf: the channel buffer
109c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * @filp: relay file pointer
110c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 *
111c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * Called when a relay file is successfully unmapped
112c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 */
113c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru        void (*buf_unmapped)(struct rchan_buf *buf,
114c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			     struct file *filp);
115c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	/*
116c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * create_buf_file - create file to represent a relay channel buffer
117c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * @filename: the name of the file to create
118c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * @parent: the parent of the file to create
119c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * @mode: the mode of the file to create
120c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * @buf: the channel buffer
121c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * @is_global: outparam - set non-zero if the buffer should be global
122c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 *
123c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * Called during relay_open(), once for each per-cpu buffer,
124c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * to allow the client to create a file to be used to
125c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * represent the corresponding channel buffer.  If the file is
126c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * created outside of relay, the parent must also exist in
127c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * that filesystem.
128c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 *
129c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * The callback should return the dentry of the file created
130c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * to represent the relay buffer.
131c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 *
132c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * Setting the is_global outparam to a non-zero value will
133c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * cause relay_open() to create a single global buffer rather
134c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * than the default set of per-cpu buffers.
135c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 *
136c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * See Documentation/filesystems/relayfs.txt for more info.
137c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 */
138c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct dentry *(*create_buf_file)(const char *filename,
139c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru					  struct dentry *parent,
140c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru					  int mode,
141c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru					  struct rchan_buf *buf,
142c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru					  int *is_global);
143c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
144c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	/*
145c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * remove_buf_file - remove file representing a relay channel buffer
146c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * @dentry: the dentry of the file to remove
147c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 *
148c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * Called during relay_close(), once for each per-cpu buffer,
149c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * to allow the client to remove a file used to represent a
150c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * channel buffer.
151c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 *
152c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 * The callback should return 0 if successful, negative if not.
153c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	 */
154c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	int (*remove_buf_file)(struct dentry *dentry);
155c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru};
156c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
157c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/*
158c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * CONFIG_RELAY kernel API, kernel/relay.c
159c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
160c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
161c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustruct rchan *relay_open(const char *base_filename,
162c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			 struct dentry *parent,
163c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			 size_t subbuf_size,
164c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			 size_t n_subbufs,
165c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			 struct rchan_callbacks *cb);
166c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruextern void relay_close(struct rchan *chan);
167c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruextern void relay_flush(struct rchan *chan);
168c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruextern void relay_subbufs_consumed(struct rchan *chan,
169c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru				   unsigned int cpu,
170c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru				   size_t consumed);
171c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruextern void relay_reset(struct rchan *chan);
172c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruextern int relay_buf_full(struct rchan_buf *buf);
173c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
174c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruextern size_t relay_switch_subbuf(struct rchan_buf *buf,
175c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru				  size_t length);
176c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
177c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/**
178c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	relay_write - write data into the channel
179c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	@chan: relay channel
180c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	@data: data to be written
181c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	@length: number of bytes to write
182c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
183c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	Writes data into the current cpu's channel buffer.
184c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
185c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	Protects the buffer by disabling interrupts.  Use this
186c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	if you might be logging from interrupt context.  Try
187c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	__relay_write() if you know you	won't be logging from
188c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	interrupt context.
189c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
190c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline void relay_write(struct rchan *chan,
191c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			       const void *data,
192c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			       size_t length)
193c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
194c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	unsigned long flags;
195c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct rchan_buf *buf;
196c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
197c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	local_irq_save(flags);
198c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	buf = chan->buf[smp_processor_id()];
199c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	if (unlikely(buf->offset + length > chan->subbuf_size))
200c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		length = relay_switch_subbuf(buf, length);
201c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	memcpy(buf->data + buf->offset, data, length);
202c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	buf->offset += length;
203c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	local_irq_restore(flags);
204c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
205c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
206c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/**
207c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	__relay_write - write data into the channel
208c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	@chan: relay channel
209c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	@data: data to be written
210c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	@length: number of bytes to write
211c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
212c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	Writes data into the current cpu's channel buffer.
213c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
214c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	Protects the buffer by disabling preemption.  Use
215c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	relay_write() if you might be logging from interrupt
216c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	context.
217c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
218c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline void __relay_write(struct rchan *chan,
219c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru				 const void *data,
220c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru				 size_t length)
221c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
222c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct rchan_buf *buf;
223c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
224c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	buf = chan->buf[get_cpu()];
225c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	if (unlikely(buf->offset + length > buf->chan->subbuf_size))
226c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		length = relay_switch_subbuf(buf, length);
227c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	memcpy(buf->data + buf->offset, data, length);
228c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	buf->offset += length;
229c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	put_cpu();
230c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
231c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
232c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/**
233c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	relay_reserve - reserve slot in channel buffer
234c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	@chan: relay channel
235c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	@length: number of bytes to reserve
236c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
237c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	Returns pointer to reserved slot, NULL if full.
238c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
239c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	Reserves a slot in the current cpu's channel buffer.
240c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	Does not protect the buffer at all - caller must provide
241c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	appropriate synchronization.
242c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
243c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline void *relay_reserve(struct rchan *chan, size_t length)
244c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
245c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	void *reserved;
246c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	struct rchan_buf *buf = chan->buf[smp_processor_id()];
247c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
248c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	if (unlikely(buf->offset + length > buf->chan->subbuf_size)) {
249c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		length = relay_switch_subbuf(buf, length);
250c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru		if (!length)
251c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru			return NULL;
252c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	}
253c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	reserved = buf->data + buf->offset;
254c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	buf->offset += length;
255c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
256c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	return reserved;
257c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
258c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
259c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/**
260c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	subbuf_start_reserve - reserve bytes at the start of a sub-buffer
261c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	@buf: relay channel buffer
262c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	@length: number of bytes to reserve
263c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *
264c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	Helper function used to reserve bytes at the beginning of
265c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru *	a sub-buffer in the subbuf_start() callback.
266c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
267c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Querustatic inline void subbuf_start_reserve(struct rchan_buf *buf,
268c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru					size_t length)
269c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru{
270c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	BUG_ON(length >= buf->chan->subbuf_size - 1);
271c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru	buf->offset = length;
272c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru}
273c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
274c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru/*
275c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru * exported relay file operations, kernel/relay.c
276c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru */
277c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queruextern struct file_operations relay_file_operations;
278c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
279c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru#endif /* _LINUX_RELAY_H */
280c559cd81139f97cecad1ad91a0b2e25a5936d53Jean-Baptiste Queru
281