Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block
* 'for-linus' of git://git.kernel.dk/linux-2.6-block: (37 commits)
splice: fix generic_file_splice_read() race with page invalidation
ramfs: enable splice write
drivers/block/pktcdvd.c: avoid useless memset
cdrom: revert commit 22a9189 (cdrom: use kmalloced buffers instead of buffers on stack)
scsi: sr avoids useless buffer allocation
block: blk_rq_map_kern uses the bounce buffers for stack buffers
block: add blk_queue_update_dma_pad
DAC960: push down BKL
pktcdvd: push BKL down into driver
paride: push ioctl down into driver
block: use get_unaligned_* helpers
block: extend queue_flag bitops
block: request_module(): use format string
Add bvec_merge_data to handle stacked devices and ->merge_bvec()
block: integrity flags can't use bit ops on unsigned short
cmdfilter: extend default read filter
sg: fix odd style (extra parenthesis) introduced by cmd filter patch
block: add bounce support to blk_rq_map_user_iov
cfq-iosched: get rid of enable_idle being unused warning
allow userspace to modify scsi command filter on per device basis
...
This commit is contained in:
@@ -64,6 +64,7 @@ struct bio_vec {
|
||||
|
||||
struct bio_set;
|
||||
struct bio;
|
||||
struct bio_integrity_payload;
|
||||
typedef void (bio_end_io_t) (struct bio *, int);
|
||||
typedef void (bio_destructor_t) (struct bio *);
|
||||
|
||||
@@ -112,6 +113,9 @@ struct bio {
|
||||
atomic_t bi_cnt; /* pin count */
|
||||
|
||||
void *bi_private;
|
||||
#if defined(CONFIG_BLK_DEV_INTEGRITY)
|
||||
struct bio_integrity_payload *bi_integrity; /* data integrity */
|
||||
#endif
|
||||
|
||||
bio_destructor_t *bi_destructor; /* destructor */
|
||||
};
|
||||
@@ -271,6 +275,29 @@ static inline void *bio_data(struct bio *bio)
|
||||
*/
|
||||
#define bio_get(bio) atomic_inc(&(bio)->bi_cnt)
|
||||
|
||||
#if defined(CONFIG_BLK_DEV_INTEGRITY)
|
||||
/*
|
||||
* bio integrity payload
|
||||
*/
|
||||
struct bio_integrity_payload {
|
||||
struct bio *bip_bio; /* parent bio */
|
||||
struct bio_vec *bip_vec; /* integrity data vector */
|
||||
|
||||
sector_t bip_sector; /* virtual start sector */
|
||||
|
||||
void *bip_buf; /* generated integrity data */
|
||||
bio_end_io_t *bip_end_io; /* saved I/O completion fn */
|
||||
|
||||
int bip_error; /* saved I/O error */
|
||||
unsigned int bip_size;
|
||||
|
||||
unsigned short bip_pool; /* pool the ivec came from */
|
||||
unsigned short bip_vcnt; /* # of integrity bio_vecs */
|
||||
unsigned short bip_idx; /* current bip_vec index */
|
||||
|
||||
struct work_struct bip_work; /* I/O completion */
|
||||
};
|
||||
#endif /* CONFIG_BLK_DEV_INTEGRITY */
|
||||
|
||||
/*
|
||||
* A bio_pair is used when we need to split a bio.
|
||||
@@ -283,10 +310,14 @@ static inline void *bio_data(struct bio *bio)
|
||||
* in bio2.bi_private
|
||||
*/
|
||||
struct bio_pair {
|
||||
struct bio bio1, bio2;
|
||||
struct bio_vec bv1, bv2;
|
||||
atomic_t cnt;
|
||||
int error;
|
||||
struct bio bio1, bio2;
|
||||
struct bio_vec bv1, bv2;
|
||||
#if defined(CONFIG_BLK_DEV_INTEGRITY)
|
||||
struct bio_integrity_payload bip1, bip2;
|
||||
struct bio_vec iv1, iv2;
|
||||
#endif
|
||||
atomic_t cnt;
|
||||
int error;
|
||||
};
|
||||
extern struct bio_pair *bio_split(struct bio *bi, mempool_t *pool,
|
||||
int first_sectors);
|
||||
@@ -333,6 +364,39 @@ extern struct bio *bio_copy_user_iov(struct request_queue *, struct sg_iovec *,
|
||||
int, int);
|
||||
extern int bio_uncopy_user(struct bio *);
|
||||
void zero_fill_bio(struct bio *bio);
|
||||
extern struct bio_vec *bvec_alloc_bs(gfp_t, int, unsigned long *, struct bio_set *);
|
||||
extern unsigned int bvec_nr_vecs(unsigned short idx);
|
||||
|
||||
/*
|
||||
* bio_set is used to allow other portions of the IO system to
|
||||
* allocate their own private memory pools for bio and iovec structures.
|
||||
* These memory pools in turn all allocate from the bio_slab
|
||||
* and the bvec_slabs[].
|
||||
*/
|
||||
#define BIO_POOL_SIZE 2
|
||||
#define BIOVEC_NR_POOLS 6
|
||||
|
||||
struct bio_set {
|
||||
mempool_t *bio_pool;
|
||||
#if defined(CONFIG_BLK_DEV_INTEGRITY)
|
||||
mempool_t *bio_integrity_pool;
|
||||
#endif
|
||||
mempool_t *bvec_pools[BIOVEC_NR_POOLS];
|
||||
};
|
||||
|
||||
struct biovec_slab {
|
||||
int nr_vecs;
|
||||
char *name;
|
||||
struct kmem_cache *slab;
|
||||
};
|
||||
|
||||
extern struct bio_set *fs_bio_set;
|
||||
|
||||
/*
|
||||
* a small number of entries is fine, not going to be performance critical.
|
||||
* basically we just need to survive
|
||||
*/
|
||||
#define BIO_SPLIT_ENTRIES 2
|
||||
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
/*
|
||||
@@ -381,5 +445,63 @@ static inline char *__bio_kmap_irq(struct bio *bio, unsigned short idx,
|
||||
__bio_kmap_irq((bio), (bio)->bi_idx, (flags))
|
||||
#define bio_kunmap_irq(buf,flags) __bio_kunmap_irq(buf, flags)
|
||||
|
||||
#if defined(CONFIG_BLK_DEV_INTEGRITY)
|
||||
|
||||
#define bip_vec_idx(bip, idx) (&(bip->bip_vec[(idx)]))
|
||||
#define bip_vec(bip) bip_vec_idx(bip, 0)
|
||||
|
||||
#define __bip_for_each_vec(bvl, bip, i, start_idx) \
|
||||
for (bvl = bip_vec_idx((bip), (start_idx)), i = (start_idx); \
|
||||
i < (bip)->bip_vcnt; \
|
||||
bvl++, i++)
|
||||
|
||||
#define bip_for_each_vec(bvl, bip, i) \
|
||||
__bip_for_each_vec(bvl, bip, i, (bip)->bip_idx)
|
||||
|
||||
static inline int bio_integrity(struct bio *bio)
|
||||
{
|
||||
#if defined(CONFIG_BLK_DEV_INTEGRITY)
|
||||
return bio->bi_integrity != NULL;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
extern struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *, gfp_t, unsigned int, struct bio_set *);
|
||||
extern struct bio_integrity_payload *bio_integrity_alloc(struct bio *, gfp_t, unsigned int);
|
||||
extern void bio_integrity_free(struct bio *, struct bio_set *);
|
||||
extern int bio_integrity_add_page(struct bio *, struct page *, unsigned int, unsigned int);
|
||||
extern int bio_integrity_enabled(struct bio *bio);
|
||||
extern int bio_integrity_set_tag(struct bio *, void *, unsigned int);
|
||||
extern int bio_integrity_get_tag(struct bio *, void *, unsigned int);
|
||||
extern int bio_integrity_prep(struct bio *);
|
||||
extern void bio_integrity_endio(struct bio *, int);
|
||||
extern void bio_integrity_advance(struct bio *, unsigned int);
|
||||
extern void bio_integrity_trim(struct bio *, unsigned int, unsigned int);
|
||||
extern void bio_integrity_split(struct bio *, struct bio_pair *, int);
|
||||
extern int bio_integrity_clone(struct bio *, struct bio *, struct bio_set *);
|
||||
extern int bioset_integrity_create(struct bio_set *, int);
|
||||
extern void bioset_integrity_free(struct bio_set *);
|
||||
extern void bio_integrity_init_slab(void);
|
||||
|
||||
#else /* CONFIG_BLK_DEV_INTEGRITY */
|
||||
|
||||
#define bio_integrity(a) (0)
|
||||
#define bioset_integrity_create(a, b) (0)
|
||||
#define bio_integrity_prep(a) (0)
|
||||
#define bio_integrity_enabled(a) (0)
|
||||
#define bio_integrity_clone(a, b, c) (0)
|
||||
#define bioset_integrity_free(a) do { } while (0)
|
||||
#define bio_integrity_free(a, b) do { } while (0)
|
||||
#define bio_integrity_endio(a, b) do { } while (0)
|
||||
#define bio_integrity_advance(a, b) do { } while (0)
|
||||
#define bio_integrity_trim(a, b, c) do { } while (0)
|
||||
#define bio_integrity_split(a, b, c) do { } while (0)
|
||||
#define bio_integrity_set_tag(a, b, c) do { } while (0)
|
||||
#define bio_integrity_get_tag(a, b, c) do { } while (0)
|
||||
#define bio_integrity_init_slab(a) do { } while (0)
|
||||
|
||||
#endif /* CONFIG_BLK_DEV_INTEGRITY */
|
||||
|
||||
#endif /* CONFIG_BLOCK */
|
||||
#endif /* __LINUX_BIO_H */
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
struct scsi_ioctl_command;
|
||||
|
||||
struct request_queue;
|
||||
typedef struct request_queue request_queue_t __deprecated;
|
||||
struct elevator_queue;
|
||||
typedef struct elevator_queue elevator_t;
|
||||
struct request_pm_state;
|
||||
@@ -34,12 +33,6 @@ struct sg_io_hdr;
|
||||
#define BLKDEV_MIN_RQ 4
|
||||
#define BLKDEV_MAX_RQ 128 /* Default maximum */
|
||||
|
||||
int put_io_context(struct io_context *ioc);
|
||||
void exit_io_context(void);
|
||||
struct io_context *get_io_context(gfp_t gfp_flags, int node);
|
||||
struct io_context *alloc_io_context(gfp_t gfp_flags, int node);
|
||||
void copy_io_context(struct io_context **pdst, struct io_context **psrc);
|
||||
|
||||
struct request;
|
||||
typedef void (rq_end_io_fn)(struct request *, int);
|
||||
|
||||
@@ -113,6 +106,7 @@ enum rq_flag_bits {
|
||||
__REQ_ALLOCED, /* request came from our alloc pool */
|
||||
__REQ_RW_META, /* metadata io request */
|
||||
__REQ_COPY_USER, /* contains copies of user pages */
|
||||
__REQ_INTEGRITY, /* integrity metadata has been remapped */
|
||||
__REQ_NR_BITS, /* stops here */
|
||||
};
|
||||
|
||||
@@ -135,6 +129,7 @@ enum rq_flag_bits {
|
||||
#define REQ_ALLOCED (1 << __REQ_ALLOCED)
|
||||
#define REQ_RW_META (1 << __REQ_RW_META)
|
||||
#define REQ_COPY_USER (1 << __REQ_COPY_USER)
|
||||
#define REQ_INTEGRITY (1 << __REQ_INTEGRITY)
|
||||
|
||||
#define BLK_MAX_CDB 16
|
||||
|
||||
@@ -259,7 +254,14 @@ typedef int (prep_rq_fn) (struct request_queue *, struct request *);
|
||||
typedef void (unplug_fn) (struct request_queue *);
|
||||
|
||||
struct bio_vec;
|
||||
typedef int (merge_bvec_fn) (struct request_queue *, struct bio *, struct bio_vec *);
|
||||
struct bvec_merge_data {
|
||||
struct block_device *bi_bdev;
|
||||
sector_t bi_sector;
|
||||
unsigned bi_size;
|
||||
unsigned long bi_rw;
|
||||
};
|
||||
typedef int (merge_bvec_fn) (struct request_queue *, struct bvec_merge_data *,
|
||||
struct bio_vec *);
|
||||
typedef void (prepare_flush_fn) (struct request_queue *, struct request *);
|
||||
typedef void (softirq_done_fn)(struct request *);
|
||||
typedef int (dma_drain_needed_fn)(struct request *);
|
||||
@@ -426,6 +428,32 @@ static inline void queue_flag_set_unlocked(unsigned int flag,
|
||||
__set_bit(flag, &q->queue_flags);
|
||||
}
|
||||
|
||||
static inline int queue_flag_test_and_clear(unsigned int flag,
|
||||
struct request_queue *q)
|
||||
{
|
||||
WARN_ON_ONCE(!queue_is_locked(q));
|
||||
|
||||
if (test_bit(flag, &q->queue_flags)) {
|
||||
__clear_bit(flag, &q->queue_flags);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int queue_flag_test_and_set(unsigned int flag,
|
||||
struct request_queue *q)
|
||||
{
|
||||
WARN_ON_ONCE(!queue_is_locked(q));
|
||||
|
||||
if (!test_bit(flag, &q->queue_flags)) {
|
||||
__set_bit(flag, &q->queue_flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline void queue_flag_set(unsigned int flag, struct request_queue *q)
|
||||
{
|
||||
WARN_ON_ONCE(!queue_is_locked(q));
|
||||
@@ -676,7 +704,6 @@ extern int blk_execute_rq(struct request_queue *, struct gendisk *,
|
||||
struct request *, int);
|
||||
extern void blk_execute_rq_nowait(struct request_queue *, struct gendisk *,
|
||||
struct request *, int, rq_end_io_fn *);
|
||||
extern int blk_verify_command(unsigned char *, int);
|
||||
extern void blk_unplug(struct request_queue *q);
|
||||
|
||||
static inline struct request_queue *bdev_get_queue(struct block_device *bdev)
|
||||
@@ -749,6 +776,7 @@ extern void blk_queue_max_segment_size(struct request_queue *, unsigned int);
|
||||
extern void blk_queue_hardsect_size(struct request_queue *, unsigned short);
|
||||
extern void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b);
|
||||
extern void blk_queue_dma_pad(struct request_queue *, unsigned int);
|
||||
extern void blk_queue_update_dma_pad(struct request_queue *, unsigned int);
|
||||
extern int blk_queue_dma_drain(struct request_queue *q,
|
||||
dma_drain_needed_fn *dma_drain_needed,
|
||||
void *buf, unsigned int size);
|
||||
@@ -802,6 +830,15 @@ static inline struct request *blk_map_queue_find_tag(struct blk_queue_tag *bqt,
|
||||
|
||||
extern int blkdev_issue_flush(struct block_device *, sector_t *);
|
||||
|
||||
/*
|
||||
* command filter functions
|
||||
*/
|
||||
extern int blk_verify_command(struct file *file, unsigned char *cmd);
|
||||
extern int blk_cmd_filter_verify_command(struct blk_scsi_cmd_filter *filter,
|
||||
unsigned char *cmd, mode_t *f_mode);
|
||||
extern int blk_register_filter(struct gendisk *disk);
|
||||
extern void blk_unregister_filter(struct gendisk *disk);
|
||||
|
||||
#define MAX_PHYS_SEGMENTS 128
|
||||
#define MAX_HW_SEGMENTS 128
|
||||
#define SAFE_MAX_SECTORS 255
|
||||
@@ -865,6 +902,105 @@ void kblockd_flush_work(struct work_struct *work);
|
||||
#define MODULE_ALIAS_BLOCKDEV_MAJOR(major) \
|
||||
MODULE_ALIAS("block-major-" __stringify(major) "-*")
|
||||
|
||||
#if defined(CONFIG_BLK_DEV_INTEGRITY)
|
||||
|
||||
#define INTEGRITY_FLAG_READ 2 /* verify data integrity on read */
|
||||
#define INTEGRITY_FLAG_WRITE 4 /* generate data integrity on write */
|
||||
|
||||
struct blk_integrity_exchg {
|
||||
void *prot_buf;
|
||||
void *data_buf;
|
||||
sector_t sector;
|
||||
unsigned int data_size;
|
||||
unsigned short sector_size;
|
||||
const char *disk_name;
|
||||
};
|
||||
|
||||
typedef void (integrity_gen_fn) (struct blk_integrity_exchg *);
|
||||
typedef int (integrity_vrfy_fn) (struct blk_integrity_exchg *);
|
||||
typedef void (integrity_set_tag_fn) (void *, void *, unsigned int);
|
||||
typedef void (integrity_get_tag_fn) (void *, void *, unsigned int);
|
||||
|
||||
struct blk_integrity {
|
||||
integrity_gen_fn *generate_fn;
|
||||
integrity_vrfy_fn *verify_fn;
|
||||
integrity_set_tag_fn *set_tag_fn;
|
||||
integrity_get_tag_fn *get_tag_fn;
|
||||
|
||||
unsigned short flags;
|
||||
unsigned short tuple_size;
|
||||
unsigned short sector_size;
|
||||
unsigned short tag_size;
|
||||
|
||||
const char *name;
|
||||
|
||||
struct kobject kobj;
|
||||
};
|
||||
|
||||
extern int blk_integrity_register(struct gendisk *, struct blk_integrity *);
|
||||
extern void blk_integrity_unregister(struct gendisk *);
|
||||
extern int blk_integrity_compare(struct block_device *, struct block_device *);
|
||||
extern int blk_rq_map_integrity_sg(struct request *, struct scatterlist *);
|
||||
extern int blk_rq_count_integrity_sg(struct request *);
|
||||
|
||||
static inline unsigned short blk_integrity_tuple_size(struct blk_integrity *bi)
|
||||
{
|
||||
if (bi)
|
||||
return bi->tuple_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct blk_integrity *bdev_get_integrity(struct block_device *bdev)
|
||||
{
|
||||
return bdev->bd_disk->integrity;
|
||||
}
|
||||
|
||||
static inline unsigned int bdev_get_tag_size(struct block_device *bdev)
|
||||
{
|
||||
struct blk_integrity *bi = bdev_get_integrity(bdev);
|
||||
|
||||
if (bi)
|
||||
return bi->tag_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int bdev_integrity_enabled(struct block_device *bdev, int rw)
|
||||
{
|
||||
struct blk_integrity *bi = bdev_get_integrity(bdev);
|
||||
|
||||
if (bi == NULL)
|
||||
return 0;
|
||||
|
||||
if (rw == READ && bi->verify_fn != NULL &&
|
||||
(bi->flags & INTEGRITY_FLAG_READ))
|
||||
return 1;
|
||||
|
||||
if (rw == WRITE && bi->generate_fn != NULL &&
|
||||
(bi->flags & INTEGRITY_FLAG_WRITE))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int blk_integrity_rq(struct request *rq)
|
||||
{
|
||||
return bio_integrity(rq->bio);
|
||||
}
|
||||
|
||||
#else /* CONFIG_BLK_DEV_INTEGRITY */
|
||||
|
||||
#define blk_integrity_rq(rq) (0)
|
||||
#define blk_rq_count_integrity_sg(a) (0)
|
||||
#define blk_rq_map_integrity_sg(a, b) (0)
|
||||
#define bdev_get_integrity(a) (0)
|
||||
#define bdev_get_tag_size(a) (0)
|
||||
#define blk_integrity_compare(a, b) (0)
|
||||
#define blk_integrity_register(a, b) (0)
|
||||
#define blk_integrity_unregister(a) do { } while (0);
|
||||
|
||||
#endif /* CONFIG_BLK_DEV_INTEGRITY */
|
||||
|
||||
#else /* CONFIG_BLOCK */
|
||||
/*
|
||||
@@ -877,17 +1013,6 @@ static inline long nr_blockdev_pages(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void exit_io_context(void)
|
||||
{
|
||||
}
|
||||
|
||||
struct io_context;
|
||||
static inline int put_io_context(struct io_context *ioc)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#endif /* CONFIG_BLOCK */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -129,6 +129,7 @@ struct blk_trace {
|
||||
u32 dev;
|
||||
struct dentry *dir;
|
||||
struct dentry *dropped_file;
|
||||
struct dentry *msg_file;
|
||||
atomic_t dropped;
|
||||
};
|
||||
|
||||
|
||||
@@ -110,6 +110,14 @@ struct hd_struct {
|
||||
#define GENHD_FL_SUPPRESS_PARTITION_INFO 32
|
||||
#define GENHD_FL_FAIL 64
|
||||
|
||||
#define BLK_SCSI_MAX_CMDS (256)
|
||||
#define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8))
|
||||
|
||||
struct blk_scsi_cmd_filter {
|
||||
unsigned long read_ok[BLK_SCSI_CMD_PER_LONG];
|
||||
unsigned long write_ok[BLK_SCSI_CMD_PER_LONG];
|
||||
struct kobject kobj;
|
||||
};
|
||||
|
||||
struct gendisk {
|
||||
int major; /* major number of driver */
|
||||
@@ -120,6 +128,7 @@ struct gendisk {
|
||||
struct hd_struct **part; /* [indexed by minor] */
|
||||
struct block_device_operations *fops;
|
||||
struct request_queue *queue;
|
||||
struct blk_scsi_cmd_filter cmd_filter;
|
||||
void *private_data;
|
||||
sector_t capacity;
|
||||
|
||||
@@ -141,6 +150,9 @@ struct gendisk {
|
||||
struct disk_stats dkstats;
|
||||
#endif
|
||||
struct work_struct async_notify;
|
||||
#ifdef CONFIG_BLK_DEV_INTEGRITY
|
||||
struct blk_integrity *integrity;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -99,4 +99,22 @@ static inline struct io_context *ioc_task_link(struct io_context *ioc)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLOCK
|
||||
int put_io_context(struct io_context *ioc);
|
||||
void exit_io_context(void);
|
||||
struct io_context *get_io_context(gfp_t gfp_flags, int node);
|
||||
struct io_context *alloc_io_context(gfp_t gfp_flags, int node);
|
||||
void copy_io_context(struct io_context **pdst, struct io_context **psrc);
|
||||
#else
|
||||
static inline void exit_io_context(void)
|
||||
{
|
||||
}
|
||||
|
||||
struct io_context;
|
||||
static inline int put_io_context(struct io_context *ioc)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user