Merge branch 'blktrace' of git://brick.kernel.dk/data/git/linux-2.6-block
* 'blktrace' of git://brick.kernel.dk/data/git/linux-2.6-block: [PATCH] Block queue IO tracing support (blktrace) as of 2006-03-23 [PATCH] relay: consolidate sendfile() and read() code [PATCH] relay: add sendfile() support [PATCH] relay: migrate from relayfs to a generic relay API
This commit is contained in:
commit
cec6062037
29 changed files with 2221 additions and 1293 deletions
|
@ -22,6 +22,7 @@ typedef struct request_queue request_queue_t;
|
|||
struct elevator_queue;
|
||||
typedef struct elevator_queue elevator_t;
|
||||
struct request_pm_state;
|
||||
struct blk_trace;
|
||||
|
||||
#define BLKDEV_MIN_RQ 4
|
||||
#define BLKDEV_MAX_RQ 128 /* Default maximum */
|
||||
|
@ -416,6 +417,8 @@ struct request_queue
|
|||
unsigned int sg_reserved_size;
|
||||
int node;
|
||||
|
||||
struct blk_trace *blk_trace;
|
||||
|
||||
/*
|
||||
* reserved for flush operations
|
||||
*/
|
||||
|
|
277
include/linux/blktrace_api.h
Normal file
277
include/linux/blktrace_api.h
Normal file
|
@ -0,0 +1,277 @@
|
|||
#ifndef BLKTRACE_H
|
||||
#define BLKTRACE_H
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/relay.h>
|
||||
|
||||
/*
|
||||
* Trace categories
|
||||
*/
|
||||
enum blktrace_cat {
|
||||
BLK_TC_READ = 1 << 0, /* reads */
|
||||
BLK_TC_WRITE = 1 << 1, /* writes */
|
||||
BLK_TC_BARRIER = 1 << 2, /* barrier */
|
||||
BLK_TC_SYNC = 1 << 3, /* barrier */
|
||||
BLK_TC_QUEUE = 1 << 4, /* queueing/merging */
|
||||
BLK_TC_REQUEUE = 1 << 5, /* requeueing */
|
||||
BLK_TC_ISSUE = 1 << 6, /* issue */
|
||||
BLK_TC_COMPLETE = 1 << 7, /* completions */
|
||||
BLK_TC_FS = 1 << 8, /* fs requests */
|
||||
BLK_TC_PC = 1 << 9, /* pc requests */
|
||||
BLK_TC_NOTIFY = 1 << 10, /* special message */
|
||||
|
||||
BLK_TC_END = 1 << 15, /* only 16-bits, reminder */
|
||||
};
|
||||
|
||||
#define BLK_TC_SHIFT (16)
|
||||
#define BLK_TC_ACT(act) ((act) << BLK_TC_SHIFT)
|
||||
|
||||
/*
|
||||
* Basic trace actions
|
||||
*/
|
||||
enum blktrace_act {
|
||||
__BLK_TA_QUEUE = 1, /* queued */
|
||||
__BLK_TA_BACKMERGE, /* back merged to existing rq */
|
||||
__BLK_TA_FRONTMERGE, /* front merge to existing rq */
|
||||
__BLK_TA_GETRQ, /* allocated new request */
|
||||
__BLK_TA_SLEEPRQ, /* sleeping on rq allocation */
|
||||
__BLK_TA_REQUEUE, /* request requeued */
|
||||
__BLK_TA_ISSUE, /* sent to driver */
|
||||
__BLK_TA_COMPLETE, /* completed by driver */
|
||||
__BLK_TA_PLUG, /* queue was plugged */
|
||||
__BLK_TA_UNPLUG_IO, /* queue was unplugged by io */
|
||||
__BLK_TA_UNPLUG_TIMER, /* queue was unplugged by timer */
|
||||
__BLK_TA_INSERT, /* insert request */
|
||||
__BLK_TA_SPLIT, /* bio was split */
|
||||
__BLK_TA_BOUNCE, /* bio was bounced */
|
||||
__BLK_TA_REMAP, /* bio was remapped */
|
||||
};
|
||||
|
||||
/*
|
||||
* Trace actions in full. Additionally, read or write is masked
|
||||
*/
|
||||
#define BLK_TA_QUEUE (__BLK_TA_QUEUE | BLK_TC_ACT(BLK_TC_QUEUE))
|
||||
#define BLK_TA_BACKMERGE (__BLK_TA_BACKMERGE | BLK_TC_ACT(BLK_TC_QUEUE))
|
||||
#define BLK_TA_FRONTMERGE (__BLK_TA_FRONTMERGE | BLK_TC_ACT(BLK_TC_QUEUE))
|
||||
#define BLK_TA_GETRQ (__BLK_TA_GETRQ | BLK_TC_ACT(BLK_TC_QUEUE))
|
||||
#define BLK_TA_SLEEPRQ (__BLK_TA_SLEEPRQ | BLK_TC_ACT(BLK_TC_QUEUE))
|
||||
#define BLK_TA_REQUEUE (__BLK_TA_REQUEUE | BLK_TC_ACT(BLK_TC_REQUEUE))
|
||||
#define BLK_TA_ISSUE (__BLK_TA_ISSUE | BLK_TC_ACT(BLK_TC_ISSUE))
|
||||
#define BLK_TA_COMPLETE (__BLK_TA_COMPLETE| BLK_TC_ACT(BLK_TC_COMPLETE))
|
||||
#define BLK_TA_PLUG (__BLK_TA_PLUG | BLK_TC_ACT(BLK_TC_QUEUE))
|
||||
#define BLK_TA_UNPLUG_IO (__BLK_TA_UNPLUG_IO | BLK_TC_ACT(BLK_TC_QUEUE))
|
||||
#define BLK_TA_UNPLUG_TIMER (__BLK_TA_UNPLUG_TIMER | BLK_TC_ACT(BLK_TC_QUEUE))
|
||||
#define BLK_TA_INSERT (__BLK_TA_INSERT | BLK_TC_ACT(BLK_TC_QUEUE))
|
||||
#define BLK_TA_SPLIT (__BLK_TA_SPLIT)
|
||||
#define BLK_TA_BOUNCE (__BLK_TA_BOUNCE)
|
||||
#define BLK_TA_REMAP (__BLK_TA_REMAP | BLK_TC_ACT(BLK_TC_QUEUE))
|
||||
|
||||
#define BLK_IO_TRACE_MAGIC 0x65617400
|
||||
#define BLK_IO_TRACE_VERSION 0x07
|
||||
|
||||
/*
|
||||
* The trace itself
|
||||
*/
|
||||
struct blk_io_trace {
|
||||
u32 magic; /* MAGIC << 8 | version */
|
||||
u32 sequence; /* event number */
|
||||
u64 time; /* in microseconds */
|
||||
u64 sector; /* disk offset */
|
||||
u32 bytes; /* transfer length */
|
||||
u32 action; /* what happened */
|
||||
u32 pid; /* who did it */
|
||||
u32 device; /* device number */
|
||||
u32 cpu; /* on what cpu did it happen */
|
||||
u16 error; /* completion error */
|
||||
u16 pdu_len; /* length of data after this trace */
|
||||
};
|
||||
|
||||
/*
|
||||
* The remap event
|
||||
*/
|
||||
struct blk_io_trace_remap {
|
||||
u32 device;
|
||||
u32 __pad;
|
||||
u64 sector;
|
||||
};
|
||||
|
||||
enum {
|
||||
Blktrace_setup = 1,
|
||||
Blktrace_running,
|
||||
Blktrace_stopped,
|
||||
};
|
||||
|
||||
struct blk_trace {
|
||||
int trace_state;
|
||||
struct rchan *rchan;
|
||||
unsigned long *sequence;
|
||||
u16 act_mask;
|
||||
u64 start_lba;
|
||||
u64 end_lba;
|
||||
u32 pid;
|
||||
u32 dev;
|
||||
struct dentry *dir;
|
||||
struct dentry *dropped_file;
|
||||
atomic_t dropped;
|
||||
};
|
||||
|
||||
/*
|
||||
* User setup structure passed with BLKTRACESTART
|
||||
*/
|
||||
struct blk_user_trace_setup {
|
||||
char name[BDEVNAME_SIZE]; /* output */
|
||||
u16 act_mask; /* input */
|
||||
u32 buf_size; /* input */
|
||||
u32 buf_nr; /* input */
|
||||
u64 start_lba;
|
||||
u64 end_lba;
|
||||
u32 pid;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_BLK_DEV_IO_TRACE)
|
||||
extern int blk_trace_ioctl(struct block_device *, unsigned, char __user *);
|
||||
extern void blk_trace_shutdown(request_queue_t *);
|
||||
extern void __blk_add_trace(struct blk_trace *, sector_t, int, int, u32, int, int, void *);
|
||||
|
||||
/**
|
||||
* blk_add_trace_rq - Add a trace for a request oriented action
|
||||
* @q: queue the io is for
|
||||
* @rq: the source request
|
||||
* @what: the action
|
||||
*
|
||||
* Description:
|
||||
* Records an action against a request. Will log the bio offset + size.
|
||||
*
|
||||
**/
|
||||
static inline void blk_add_trace_rq(struct request_queue *q, struct request *rq,
|
||||
u32 what)
|
||||
{
|
||||
struct blk_trace *bt = q->blk_trace;
|
||||
int rw = rq->flags & 0x07;
|
||||
|
||||
if (likely(!bt))
|
||||
return;
|
||||
|
||||
if (blk_pc_request(rq)) {
|
||||
what |= BLK_TC_ACT(BLK_TC_PC);
|
||||
__blk_add_trace(bt, 0, rq->data_len, rw, what, rq->errors, sizeof(rq->cmd), rq->cmd);
|
||||
} else {
|
||||
what |= BLK_TC_ACT(BLK_TC_FS);
|
||||
__blk_add_trace(bt, rq->hard_sector, rq->hard_nr_sectors << 9, rw, what, rq->errors, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* blk_add_trace_bio - Add a trace for a bio oriented action
|
||||
* @q: queue the io is for
|
||||
* @bio: the source bio
|
||||
* @what: the action
|
||||
*
|
||||
* Description:
|
||||
* Records an action against a bio. Will log the bio offset + size.
|
||||
*
|
||||
**/
|
||||
static inline void blk_add_trace_bio(struct request_queue *q, struct bio *bio,
|
||||
u32 what)
|
||||
{
|
||||
struct blk_trace *bt = q->blk_trace;
|
||||
|
||||
if (likely(!bt))
|
||||
return;
|
||||
|
||||
__blk_add_trace(bt, bio->bi_sector, bio->bi_size, bio->bi_rw, what, !bio_flagged(bio, BIO_UPTODATE), 0, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* blk_add_trace_generic - Add a trace for a generic action
|
||||
* @q: queue the io is for
|
||||
* @bio: the source bio
|
||||
* @rw: the data direction
|
||||
* @what: the action
|
||||
*
|
||||
* Description:
|
||||
* Records a simple trace
|
||||
*
|
||||
**/
|
||||
static inline void blk_add_trace_generic(struct request_queue *q,
|
||||
struct bio *bio, int rw, u32 what)
|
||||
{
|
||||
struct blk_trace *bt = q->blk_trace;
|
||||
|
||||
if (likely(!bt))
|
||||
return;
|
||||
|
||||
if (bio)
|
||||
blk_add_trace_bio(q, bio, what);
|
||||
else
|
||||
__blk_add_trace(bt, 0, 0, rw, what, 0, 0, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* blk_add_trace_pdu_int - Add a trace for a bio with an integer payload
|
||||
* @q: queue the io is for
|
||||
* @what: the action
|
||||
* @bio: the source bio
|
||||
* @pdu: the integer payload
|
||||
*
|
||||
* Description:
|
||||
* Adds a trace with some integer payload. This might be an unplug
|
||||
* option given as the action, with the depth at unplug time given
|
||||
* as the payload
|
||||
*
|
||||
**/
|
||||
static inline void blk_add_trace_pdu_int(struct request_queue *q, u32 what,
|
||||
struct bio *bio, unsigned int pdu)
|
||||
{
|
||||
struct blk_trace *bt = q->blk_trace;
|
||||
u64 rpdu = cpu_to_be64(pdu);
|
||||
|
||||
if (likely(!bt))
|
||||
return;
|
||||
|
||||
if (bio)
|
||||
__blk_add_trace(bt, bio->bi_sector, bio->bi_size, bio->bi_rw, what, !bio_flagged(bio, BIO_UPTODATE), sizeof(rpdu), &rpdu);
|
||||
else
|
||||
__blk_add_trace(bt, 0, 0, 0, what, 0, sizeof(rpdu), &rpdu);
|
||||
}
|
||||
|
||||
/**
|
||||
* blk_add_trace_remap - Add a trace for a remap operation
|
||||
* @q: queue the io is for
|
||||
* @bio: the source bio
|
||||
* @dev: target device
|
||||
* @from: source sector
|
||||
* @to: target sector
|
||||
*
|
||||
* Description:
|
||||
* Device mapper or raid target sometimes need to split a bio because
|
||||
* it spans a stripe (or similar). Add a trace for that action.
|
||||
*
|
||||
**/
|
||||
static inline void blk_add_trace_remap(struct request_queue *q, struct bio *bio,
|
||||
dev_t dev, sector_t from, sector_t to)
|
||||
{
|
||||
struct blk_trace *bt = q->blk_trace;
|
||||
struct blk_io_trace_remap r;
|
||||
|
||||
if (likely(!bt))
|
||||
return;
|
||||
|
||||
r.device = cpu_to_be32(dev);
|
||||
r.sector = cpu_to_be64(to);
|
||||
|
||||
__blk_add_trace(bt, from, bio->bi_size, bio->bi_rw, BLK_TA_REMAP, !bio_flagged(bio, BIO_UPTODATE), sizeof(r), &r);
|
||||
}
|
||||
|
||||
#else /* !CONFIG_BLK_DEV_IO_TRACE */
|
||||
#define blk_trace_ioctl(bdev, cmd, arg) (-ENOTTY)
|
||||
#define blk_trace_shutdown(q) do { } while (0)
|
||||
#define blk_add_trace_rq(q, rq, what) do { } while (0)
|
||||
#define blk_add_trace_bio(q, rq, what) do { } while (0)
|
||||
#define blk_add_trace_generic(q, rq, rw, what) do { } while (0)
|
||||
#define blk_add_trace_pdu_int(q, what, bio, pdu) do { } while (0)
|
||||
#define blk_add_trace_remap(q, bio, dev, f, t) do {} while (0)
|
||||
#endif /* CONFIG_BLK_DEV_IO_TRACE */
|
||||
|
||||
#endif
|
|
@ -97,6 +97,10 @@ COMPATIBLE_IOCTL(BLKRRPART)
|
|||
COMPATIBLE_IOCTL(BLKFLSBUF)
|
||||
COMPATIBLE_IOCTL(BLKSECTSET)
|
||||
COMPATIBLE_IOCTL(BLKSSZGET)
|
||||
COMPATIBLE_IOCTL(BLKTRACESTART)
|
||||
COMPATIBLE_IOCTL(BLKTRACESTOP)
|
||||
COMPATIBLE_IOCTL(BLKTRACESETUP)
|
||||
COMPATIBLE_IOCTL(BLKTRACETEARDOWN)
|
||||
ULONG_IOCTL(BLKRASET)
|
||||
ULONG_IOCTL(BLKFRASET)
|
||||
/* RAID */
|
||||
|
|
|
@ -197,6 +197,10 @@ extern int dir_notify_enable;
|
|||
#define BLKBSZGET _IOR(0x12,112,size_t)
|
||||
#define BLKBSZSET _IOW(0x12,113,size_t)
|
||||
#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
|
||||
#define BLKTRACESETUP _IOWR(0x12,115,struct blk_user_trace_setup)
|
||||
#define BLKTRACESTART _IO(0x12,116)
|
||||
#define BLKTRACESTOP _IO(0x12,117)
|
||||
#define BLKTRACETEARDOWN _IO(0x12,118)
|
||||
|
||||
#define BMAP_IOCTL 1 /* obsolete - kept for compatibility */
|
||||
#define FIBMAP _IO(0x00,1) /* bmap access */
|
||||
|
|
281
include/linux/relay.h
Normal file
281
include/linux/relay.h
Normal file
|
@ -0,0 +1,281 @@
|
|||
/*
|
||||
* linux/include/linux/relay.h
|
||||
*
|
||||
* Copyright (C) 2002, 2003 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp
|
||||
* Copyright (C) 1999, 2000, 2001, 2002 - Karim Yaghmour (karim@opersys.com)
|
||||
*
|
||||
* CONFIG_RELAY definitions and declarations
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_RELAY_H
|
||||
#define _LINUX_RELAY_H
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/kref.h>
|
||||
|
||||
/* Needs a _much_ better name... */
|
||||
#define FIX_SIZE(x) ((((x) - 1) & PAGE_MASK) + PAGE_SIZE)
|
||||
|
||||
/*
|
||||
* Tracks changes to rchan/rchan_buf structs
|
||||
*/
|
||||
#define RELAYFS_CHANNEL_VERSION 6
|
||||
|
||||
/*
|
||||
* Per-cpu relay channel buffer
|
||||
*/
|
||||
struct rchan_buf
|
||||
{
|
||||
void *start; /* start of channel buffer */
|
||||
void *data; /* start of current sub-buffer */
|
||||
size_t offset; /* current offset into sub-buffer */
|
||||
size_t subbufs_produced; /* count of sub-buffers produced */
|
||||
size_t subbufs_consumed; /* count of sub-buffers consumed */
|
||||
struct rchan *chan; /* associated channel */
|
||||
wait_queue_head_t read_wait; /* reader wait queue */
|
||||
struct work_struct wake_readers; /* reader wake-up work struct */
|
||||
struct dentry *dentry; /* channel file dentry */
|
||||
struct kref kref; /* channel buffer refcount */
|
||||
struct page **page_array; /* array of current buffer pages */
|
||||
unsigned int page_count; /* number of current buffer pages */
|
||||
unsigned int finalized; /* buffer has been finalized */
|
||||
size_t *padding; /* padding counts per sub-buffer */
|
||||
size_t prev_padding; /* temporary variable */
|
||||
size_t bytes_consumed; /* bytes consumed in cur read subbuf */
|
||||
unsigned int cpu; /* this buf's cpu */
|
||||
} ____cacheline_aligned;
|
||||
|
||||
/*
|
||||
* Relay channel data structure
|
||||
*/
|
||||
struct rchan
|
||||
{
|
||||
u32 version; /* the version of this struct */
|
||||
size_t subbuf_size; /* sub-buffer size */
|
||||
size_t n_subbufs; /* number of sub-buffers per buffer */
|
||||
size_t alloc_size; /* total buffer size allocated */
|
||||
struct rchan_callbacks *cb; /* client callbacks */
|
||||
struct kref kref; /* channel refcount */
|
||||
void *private_data; /* for user-defined data */
|
||||
size_t last_toobig; /* tried to log event > subbuf size */
|
||||
struct rchan_buf *buf[NR_CPUS]; /* per-cpu channel buffers */
|
||||
};
|
||||
|
||||
/*
|
||||
* Relay channel client callbacks
|
||||
*/
|
||||
struct rchan_callbacks
|
||||
{
|
||||
/*
|
||||
* subbuf_start - called on buffer-switch to a new sub-buffer
|
||||
* @buf: the channel buffer containing the new sub-buffer
|
||||
* @subbuf: the start of the new sub-buffer
|
||||
* @prev_subbuf: the start of the previous sub-buffer
|
||||
* @prev_padding: unused space at the end of previous sub-buffer
|
||||
*
|
||||
* The client should return 1 to continue logging, 0 to stop
|
||||
* logging.
|
||||
*
|
||||
* NOTE: subbuf_start will also be invoked when the buffer is
|
||||
* created, so that the first sub-buffer can be initialized
|
||||
* if necessary. In this case, prev_subbuf will be NULL.
|
||||
*
|
||||
* NOTE: the client can reserve bytes at the beginning of the new
|
||||
* sub-buffer by calling subbuf_start_reserve() in this callback.
|
||||
*/
|
||||
int (*subbuf_start) (struct rchan_buf *buf,
|
||||
void *subbuf,
|
||||
void *prev_subbuf,
|
||||
size_t prev_padding);
|
||||
|
||||
/*
|
||||
* buf_mapped - relay buffer mmap notification
|
||||
* @buf: the channel buffer
|
||||
* @filp: relay file pointer
|
||||
*
|
||||
* Called when a relay file is successfully mmapped
|
||||
*/
|
||||
void (*buf_mapped)(struct rchan_buf *buf,
|
||||
struct file *filp);
|
||||
|
||||
/*
|
||||
* buf_unmapped - relay buffer unmap notification
|
||||
* @buf: the channel buffer
|
||||
* @filp: relay file pointer
|
||||
*
|
||||
* Called when a relay file is successfully unmapped
|
||||
*/
|
||||
void (*buf_unmapped)(struct rchan_buf *buf,
|
||||
struct file *filp);
|
||||
/*
|
||||
* create_buf_file - create file to represent a relay channel buffer
|
||||
* @filename: the name of the file to create
|
||||
* @parent: the parent of the file to create
|
||||
* @mode: the mode of the file to create
|
||||
* @buf: the channel buffer
|
||||
* @is_global: outparam - set non-zero if the buffer should be global
|
||||
*
|
||||
* Called during relay_open(), once for each per-cpu buffer,
|
||||
* to allow the client to create a file to be used to
|
||||
* represent the corresponding channel buffer. If the file is
|
||||
* created outside of relay, the parent must also exist in
|
||||
* that filesystem.
|
||||
*
|
||||
* The callback should return the dentry of the file created
|
||||
* to represent the relay buffer.
|
||||
*
|
||||
* Setting the is_global outparam to a non-zero value will
|
||||
* cause relay_open() to create a single global buffer rather
|
||||
* than the default set of per-cpu buffers.
|
||||
*
|
||||
* See Documentation/filesystems/relayfs.txt for more info.
|
||||
*/
|
||||
struct dentry *(*create_buf_file)(const char *filename,
|
||||
struct dentry *parent,
|
||||
int mode,
|
||||
struct rchan_buf *buf,
|
||||
int *is_global);
|
||||
|
||||
/*
|
||||
* remove_buf_file - remove file representing a relay channel buffer
|
||||
* @dentry: the dentry of the file to remove
|
||||
*
|
||||
* Called during relay_close(), once for each per-cpu buffer,
|
||||
* to allow the client to remove a file used to represent a
|
||||
* channel buffer.
|
||||
*
|
||||
* The callback should return 0 if successful, negative if not.
|
||||
*/
|
||||
int (*remove_buf_file)(struct dentry *dentry);
|
||||
};
|
||||
|
||||
/*
|
||||
* CONFIG_RELAY kernel API, kernel/relay.c
|
||||
*/
|
||||
|
||||
struct rchan *relay_open(const char *base_filename,
|
||||
struct dentry *parent,
|
||||
size_t subbuf_size,
|
||||
size_t n_subbufs,
|
||||
struct rchan_callbacks *cb);
|
||||
extern void relay_close(struct rchan *chan);
|
||||
extern void relay_flush(struct rchan *chan);
|
||||
extern void relay_subbufs_consumed(struct rchan *chan,
|
||||
unsigned int cpu,
|
||||
size_t consumed);
|
||||
extern void relay_reset(struct rchan *chan);
|
||||
extern int relay_buf_full(struct rchan_buf *buf);
|
||||
|
||||
extern size_t relay_switch_subbuf(struct rchan_buf *buf,
|
||||
size_t length);
|
||||
|
||||
/**
|
||||
* relay_write - write data into the channel
|
||||
* @chan: relay channel
|
||||
* @data: data to be written
|
||||
* @length: number of bytes to write
|
||||
*
|
||||
* Writes data into the current cpu's channel buffer.
|
||||
*
|
||||
* Protects the buffer by disabling interrupts. Use this
|
||||
* if you might be logging from interrupt context. Try
|
||||
* __relay_write() if you know you won't be logging from
|
||||
* interrupt context.
|
||||
*/
|
||||
static inline void relay_write(struct rchan *chan,
|
||||
const void *data,
|
||||
size_t length)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct rchan_buf *buf;
|
||||
|
||||
local_irq_save(flags);
|
||||
buf = chan->buf[smp_processor_id()];
|
||||
if (unlikely(buf->offset + length > chan->subbuf_size))
|
||||
length = relay_switch_subbuf(buf, length);
|
||||
memcpy(buf->data + buf->offset, data, length);
|
||||
buf->offset += length;
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* __relay_write - write data into the channel
|
||||
* @chan: relay channel
|
||||
* @data: data to be written
|
||||
* @length: number of bytes to write
|
||||
*
|
||||
* Writes data into the current cpu's channel buffer.
|
||||
*
|
||||
* Protects the buffer by disabling preemption. Use
|
||||
* relay_write() if you might be logging from interrupt
|
||||
* context.
|
||||
*/
|
||||
static inline void __relay_write(struct rchan *chan,
|
||||
const void *data,
|
||||
size_t length)
|
||||
{
|
||||
struct rchan_buf *buf;
|
||||
|
||||
buf = chan->buf[get_cpu()];
|
||||
if (unlikely(buf->offset + length > buf->chan->subbuf_size))
|
||||
length = relay_switch_subbuf(buf, length);
|
||||
memcpy(buf->data + buf->offset, data, length);
|
||||
buf->offset += length;
|
||||
put_cpu();
|
||||
}
|
||||
|
||||
/**
|
||||
* relay_reserve - reserve slot in channel buffer
|
||||
* @chan: relay channel
|
||||
* @length: number of bytes to reserve
|
||||
*
|
||||
* Returns pointer to reserved slot, NULL if full.
|
||||
*
|
||||
* Reserves a slot in the current cpu's channel buffer.
|
||||
* Does not protect the buffer at all - caller must provide
|
||||
* appropriate synchronization.
|
||||
*/
|
||||
static inline void *relay_reserve(struct rchan *chan, size_t length)
|
||||
{
|
||||
void *reserved;
|
||||
struct rchan_buf *buf = chan->buf[smp_processor_id()];
|
||||
|
||||
if (unlikely(buf->offset + length > buf->chan->subbuf_size)) {
|
||||
length = relay_switch_subbuf(buf, length);
|
||||
if (!length)
|
||||
return NULL;
|
||||
}
|
||||
reserved = buf->data + buf->offset;
|
||||
buf->offset += length;
|
||||
|
||||
return reserved;
|
||||
}
|
||||
|
||||
/**
|
||||
* subbuf_start_reserve - reserve bytes at the start of a sub-buffer
|
||||
* @buf: relay channel buffer
|
||||
* @length: number of bytes to reserve
|
||||
*
|
||||
* Helper function used to reserve bytes at the beginning of
|
||||
* a sub-buffer in the subbuf_start() callback.
|
||||
*/
|
||||
static inline void subbuf_start_reserve(struct rchan_buf *buf,
|
||||
size_t length)
|
||||
{
|
||||
BUG_ON(length >= buf->chan->subbuf_size - 1);
|
||||
buf->offset = length;
|
||||
}
|
||||
|
||||
/*
|
||||
* exported relay file operations, kernel/relay.c
|
||||
*/
|
||||
extern struct file_operations relay_file_operations;
|
||||
|
||||
#endif /* _LINUX_RELAY_H */
|
||||
|
|
@ -706,6 +706,7 @@ struct task_struct {
|
|||
prio_array_t *array;
|
||||
|
||||
unsigned short ioprio;
|
||||
unsigned int btrace_seq;
|
||||
|
||||
unsigned long sleep_avg;
|
||||
unsigned long long timestamp, last_ran;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue