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